JNI引用C++dll若干问题总结-如何导出C++中的类成员函数
2016-09-14 13:51
579 查看
最近做项目使用JNI引用C++的dll,在此记录遇到的问题。
1.如何导出C++中的类
大家都知道JNI只能导出全局函数,至少我搜索了好久都没看到过有导出类的,貌似不可以。当然如果可以就更好了。
那么既然使用的是C++语言,如果不使用类的话,那还不如直接使用C。总之,面向对象编程就是比面向过程”艺术”。所以就遇到个问题,C++类中的成员函数如何使用JNI导出?JNI只能导出全局函数。
所以,我们可以采用一个折中的办法,为每一个类成员函数写一个全局导出函数,在cpp实现文件中new 一个类对象,在全局函数中使用这个类对象调用成员函数,最后写一个全局函数释放这个类对象。
例如:
要想通过JNI导出Dog类的eat成员函数,当然可以有多个成员函数,我们新建一个文件:
因为成员函数必须使用类的实例调用,所以我们可以在export.cpp中实例化这个类:
这样大概就可以了。手写的代码,不保证能运行,但是就是这思路。
2.在java中System.loadLibrary()注意的问题
<1>如果是64为的jdk必须加载64位的dll,debug版本的和release版本的都没关系,可以相互调用,但是必须是64位的。
<2>必须先加载依赖库,比如你要引用的a.dll还引用着b.dll,就必须先使用System.loadLibrary加载b.dll,再加载a.dll,有时候一个dll依赖多个dll的时候,需要注意加载的顺序。
<3>有些64位的dll引用的竟然是32位的dll,竟然也能编译过了。比如,我的项目中引用libcurl.dll,再loadLibrary的时候,报 %1 libcurl不是win32应用程序,我就纳闷了。然后在dependency工具下看到其引用的SSLEAY32.dll和LIBEAY32.dll竟然是32位的,估计是系统目录下的,因为我引用的dll目录中没有这两个dll,如果没有找的话,编译Java程序的时候会报找不到依赖库,但是没报这个错,说明是在系统目录下找到的。所以,我找到了SSLEAY32.dll和LIBEAY32.dll这两个的64位版本的,就可以了。
1.如何导出C++中的类
大家都知道JNI只能导出全局函数,至少我搜索了好久都没看到过有导出类的,貌似不可以。当然如果可以就更好了。
那么既然使用的是C++语言,如果不使用类的话,那还不如直接使用C。总之,面向对象编程就是比面向过程”艺术”。所以就遇到个问题,C++类中的成员函数如何使用JNI导出?JNI只能导出全局函数。
所以,我们可以采用一个折中的办法,为每一个类成员函数写一个全局导出函数,在cpp实现文件中new 一个类对象,在全局函数中使用这个类对象调用成员函数,最后写一个全局函数释放这个类对象。
例如:
//Dog.h class Dog() { public: Dog(); ~Dog(); void eat(){std::cout<<"eat bone\n";}; ... }
要想通过JNI导出Dog类的eat成员函数,当然可以有多个成员函数,我们新建一个文件:
//export.h #include "jni.h" extern "C" { JNIEXPORT void JNICALL JAVA_com_wj_demo_init(JNIEnv *env, jobject); JNIEXPORT void JNICALL JAVA_com_wj_demo_eat(JNIEnv *env, jobject); JNIEXPORT void JNICALL JAVA_com_wj_demo_release(JNIEnv *env, jobject); }
因为成员函数必须使用类的实例调用,所以我们可以在export.cpp中实例化这个类:
//export.cpp #include "Dog.h" Dog *dog ; JNIEXPORT void JNICALL JAVA_com_wj_demo_init(JNIEnv *env, jobject) { dog = new Dog(); } JNIEXPORT void JNICALL JAVA_com_wj_demo_eat(JNIEnv *env, jobject) { dog->eat(); } JNIEXPORT void JNICALL JAVA_com_wj_demo_release(JNIEnv *env, jobject) { dog->~Dog(); }
这样大概就可以了。手写的代码,不保证能运行,但是就是这思路。
2.在java中System.loadLibrary()注意的问题
<1>如果是64为的jdk必须加载64位的dll,debug版本的和release版本的都没关系,可以相互调用,但是必须是64位的。
<2>必须先加载依赖库,比如你要引用的a.dll还引用着b.dll,就必须先使用System.loadLibrary加载b.dll,再加载a.dll,有时候一个dll依赖多个dll的时候,需要注意加载的顺序。
<3>有些64位的dll引用的竟然是32位的dll,竟然也能编译过了。比如,我的项目中引用libcurl.dll,再loadLibrary的时候,报 %1 libcurl不是win32应用程序,我就纳闷了。然后在dependency工具下看到其引用的SSLEAY32.dll和LIBEAY32.dll竟然是32位的,估计是系统目录下的,因为我引用的dll目录中没有这两个dll,如果没有找的话,编译Java程序的时候会报找不到依赖库,但是没报这个错,说明是在系统目录下找到的。所以,我找到了SSLEAY32.dll和LIBEAY32.dll这两个的64位版本的,就可以了。
相关文章推荐
- 如何生成DLL文件并导出函数及如何在C++或C#中调用DLL中导出的函数
- C++学习总结_成员函数的声明和实现需要注意问题
- C++关于参数为const引用类型的函数调用参数成员函数的一个问题
- 关于C/C++中二维数组、指针的引用等若干问题的总结
- 安装新的Matlab工具箱前后的若干问题(流水总结帖-如何安装,函数重名问题,安装后出错问题)
- c++对象成员函数返回自身引用时出现的诡异问题及解决办法
- C++学习总结(十一)——类的静态函数,成员函数的默认参数,类中包含引用和常量
- C++静态库中使用_declspec(dllexport) 不能导出函数的问题
- 关于在C/C++语言中,函数如何返回数组,数组如何作为参数传递以及返回数组的函数该如何调用问题的总结
- c++对象成员函数返回自身引用时出现的诡异问题及解决办法
- C++之不同对象的成员函数如何引用指定对象的数据成员
- 在VC6.0中创建和使用静态链接库&amp;amp;&amp;amp;C如何调用C++ 成员函数
- DLL导出函数小问题
- 如何选择DLL中函数的导出方式
- dll的导出 解决函数名称改写带来的问题
- 你是如何处理“对非共享成员的引用要求对象引用”这个问题的?
- 总结java方法(函数)传值和传引用的问题
- C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)
- c++ 如何给类的非静态常量或引用成员赋值
- C#中调用C++的dll的参数为指针类型的导出函数