65,194
社区成员




我在调用OPENJDK的JVM.DLL的时候,使用64位的DLL可以直接用MINGW32编译器调用,但32位下JVM.DLL提示UNDEFINED SYMBOL.我猜测可能是因为编译器不同(VS编译导致的)所以无法找到符号。但另一个疑问来了
既然是同一家公司产的DLL,版本是相同的,就是平台一个是32位,一个是64位,应该不大可能会产生不同的DLL导出符号吧?请问我是不是遗漏了什么,导致无法引入DLL方式使用
当我把 _JNI_IMPORT_OR_EXPORT_ //JNIIMPORT注释掉的时候,是可以正常编译链接并启动的,但是会提示其他错误
似乎跟链接无关,我就想,是不是跟//JNIIMPORT 有关?
GCC下这个不一样吗
#ifdef _JNI_IMPLEMENTATION_
#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
#else
#define _JNI_IMPORT_OR_EXPORT_ //JNIIMPORT
#endif
#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)
我知道导出导入跟
#define JNIEXPORT __declspec(dllexport) #define JNIIMPORT __declspec(dllimport)
有很大的关系,但不清楚的是,为何去掉这个之后,链接库就可以使用了呢?按理来说不同的VS GCC下这个修饰符是不一样的,他们是如何做到通用的呢,为何去掉这个以后__declspec(dllimport),就可以隐式调用DLL 呢?如何加上__declspec(dllimport)并且实现调用成功呢?
网上看到不少关于__declspec(dllimport)的套路,总体是不加这段代码也可以实现导入,但效率受到影响,所以我就想问下,如何加上这段代码并且实现调用。
PS:请不要给我介绍LOADLIBRARY的方式使用DLL。
因为那个DLL导出的符号名是C++名,而C++ Name Mangling,这个是没有语言标准的,与编译器相关,甚至同一编译器的不同版本都不能保证一致。
这个关系到符号的命名规则, 比如一个C++函数 DllGetActionClass
在C++系统中他的符号默认名称是: ?DllGetActionClass@@YGPAXXZ
一般导出方式(C方式)的名字是: DllGetActionClass
添加申明后会修改默认名称改为 DllGetActionClass
其他地方用默认名称就会找不到
我个人习惯的做法是不修改默认名称, 然后一个函数导出两个符号, 如上面函数在VS中
#pragma comment(linker, "/EXPORT:DllGetActionClass=?DllGetActionClass@@YGPAXXZ")
#pragma comment(linker, "/EXPORT:?DllGetActionClass@@YGPAXXZ")
学会使用
dumpbin(Windows)
objdump(Linux)