项目中要实现java调用C++的dll,先实现个简单的加法、减法的案例。本案例为个人记录,为大家提供一些参考。
总体思路:先在Java中建立一个类--------通过javac命令生成.class--------再由javah命令生成.h-------然后将.h复制到VC++下-------由VC++实现具体函数--------编译通过后生成DLL-------将DLL放入Java项目中调用。over
1、使用Java开发工具(IntelliJ IDEA)建一个java项目,建一个java类。【你的电脑要装jdk哦】
public class Java2cpp {
static{
System.loadLibrary("javaCallcpp");
}
public native int DLL_ADD(int a,int b);//加法
public native int DLL_SUB(int a,int b);//减法
public native int DLL_MUL(int a,int b);//乘法
public static void main(String[] args) {
int sum=0,ans1=0,ans2=0;
Java2cpp test=new Java2cpp();
sum=test.DLL_ADD(6,4);
ans1=test.DLL_SUB(7,2);
ans2=test.DLL_MUL(9,3);
System.out.println("Java call cpp dll result:"+sum+" "+ans1+" "+ans2);
}
}
类名可根据实际起,这里写了个:Java2cpp(这个文件后边将生成一个C++头文件);
System.loadLibrary("javaCallcpp");中的javaCallcpp为C++的接口项目名,一会会生成一个该名称的dll文件;
2、编译文件
下边会用到两个命令:javac和javah,我遇到过在另一台电脑不支持javah命令,提示不是内部指令。所以在这台电脑上先试了一下这两个命令,发现可以运行。
分析javah命令不可用原因应该是下方警告,之后会再用另一个电脑试试。
打开java类所在路径,在路径框输入cmd回车可直接进入该路径下,如下图,
先输入javac Java2cpp.java会生成同名的.class文件;
在输入javah Java2cpp会生成同名的.h文件。【在这可能会遇到些错误,可参考这句:这一步往往会失败,另一种方法可以成功,进入eclipse项目的目录,进入bin文件夹,执行命令javah -classpath . -jni 包名.类名(com.test.jni.Java2cpp),然后生成了com_test_jni_Java2cpp.h】
3、新建VC++项目:如下图:
项目自动生成文件如下图:
4、把第二步生成的头文件拷进项目文件夹。这里还需要一个stdafx.h文件,我这种方式生成项目没有这文件,使用Win32项目那种方式会生成,目前电脑环境没安装相关插件。
5、新建头文件dllApi,并添加如下代码:
#include "Java2cpp.h"
int DLL_API_ADD(int a, int b);
int DLL_API_SUB(int a, int b);
int DLL_API_MUL(int a, int b);
int DLL_API_DIV(int a, int b);
6、新建dllApi.cpp源文件实现上述方法,代码如下:
#include "stdafx.h"
#include <iostream>
#include "dllApi.h"
int DLL_API_ADD(int a, int b)
{
return (a + b);
}
int DLL_API_SUB(int a, int b)
{
return (a - b);
}
int DLL_API_MUL(int a, int b)
{
return (a*b);
}
7、在javaCallcpp.cpp中添加代码实现Java2cpp.h中的方法,添加完之后代码如下:【注意其中有一部分是自动生成代码】
#include "stdafx.h"
#include "pch.h"
#include "framework.h"
#include "javaCallcpp.h"
#include "Java2cpp.h"
#include "dllApi.h"
// 这是导出变量的一个示例
JAVACALLCPP_API int njavaCallcpp=0;
// 这是导出函数的一个示例。
JAVACALLCPP_API int fnjavaCallcpp(void)
{
return 0;
}
// 这是已导出类的构造函数。
CjavaCallcpp::CjavaCallcpp()
{
return;
}
JNIEXPORT jint JNICALL Java_Java2cpp_DLL_1ADD(JNIEnv *env, jobject obj, jint a, jint b) {
int var = 0;
var = DLL_API_ADD(a, b);
return var;
}
JNIEXPORT jint JNICALL Java_Java2cpp_DLL_1SUB(JNIEnv *env, jobject obj, jint a, jint b) {
int var = 0;
var = DLL_API_SUB(a, b);
return var;
}
JNIEXPORT jint JNICALL Java_Java2cpp_DLL_1MUL(JNIEnv *env, jobject obj, jint a, jint b) {
int var = 0;
var = DLL_API_MUL(a, b);
return var;
}
8、此时生成项目,报错如下:
9、添加如下配置:这两个路径中包含:jni.h和jni_md.h文件
10、此时生成我这项目还报错,根据提示改一下。
11、加上这句话,就生成成功了。
12、将生成的JAVACALLCPP.dll拷贝到java项目下,点击java开发工具的生成会输入如下下图的错误,分析为不能调用32位dll。【一些文章写出将C++的dll放到jdk或者jre的bin文件夹下,可以都放放试试】
13、改下这个配置,再重新生成,并把生成的64位dll重新放到java中。【目前接触到一些封装好的C++接口大都是32位的dll,实际做项目时C++的32位若不能改变,还需考虑改变如何java那的位数】
14、生成成功后,在Java那调用时又出现这个错误,分析为javaCallcpp.cpp中的DLL_ADD方法报错。
报错位置如下图:修改后再次生成并放到java中调用。
15、修改后,重新调用结果成功:
总结:在实际C++接口中会涉及C++类型和java类型的对应,在之后会总结记录下。
本案例的实现参考自如下链接和其他文章:(在此感谢分享)
https://www.cnblogs.com/xumaojun/p/8523085.html