您的位置:首页 > 编程语言 > C语言/C++

JNI引用C++dll若干问题总结-如何导出C++中的类成员函数

2016-09-14 13:51 579 查看
最近做项目使用JNI引用C++的dll,在此记录遇到的问题。

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位版本的,就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JNI C++ dll
相关文章推荐