且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在Windows上使用GCC编译DLL的问题

更新时间:2023-09-26 09:00:10

你不想让你的功能 static 因为这给他们内部链接。错误信息告诉您,这与导出的功能不兼容。您的JNI功能需要具有外部链接。这可以通过用 extern 替换 static 来实现。但是,由于外部链接是函数的默认值,您可以简单地删除 static 链接说明符,省略 extern 。 p>

您还需要指定C连接,因为您正在编译为C ++而不是C。使用 externC 。如果使用默认的C ++连接,那么最终会出现C ++名称的错误,我猜想是链接器错误的原因。



所以你的代码应该是这样的: / p>

  #include< jni.h> 

externC
{

JNIEXPORT void JNICALL Java_com_me_package_ClassName_Moo
(JNIEnv * env,jclass clazz)
{
的printf( 哞\\\
!);
}

}


I am using MinGW (not Cygwin) and trying to get some OSS code which I have successfully ported to the Mac to run on Windows. The desired final build is a .DLL usable as a JNI library (this is a .jnilib on the Mac), but I am having trouble compiling the last .cpp file which wraps the interface.

The issue is that every function in my .cpp file generates an error in the following form upon compilation:

g++ -I/various/such/entries -D_inline=__inline -I/c/java/include -I/c/java/include/win32 -c -o com_me_package_ClassName.o com_me_package_ClassName.cpp
com_me_package_ClassName.cpp:84:31: error: external linkage required for symbol 'void Java_com_me_package_ClassName_Moo(JNIEnv*, jclass)' because of 'dllexport' attribute
// ditto the above for every such function

Let's look at the one function whose error is shown above:

#include <jni.h> // of course this is in here
static JNIEXPORT void JNICALL Java_com_me_package_ClassName_Moo
    (JNIEnv *env, jclass clazz) {
printf("Moo!\n");
}

After some Googling of this, I saw someone else had a project where "static" functions were an issue, so I tried adding the following hack to the .cpp file before any of the functions that created the error:

#ifdef WIN32
#define static 
#endif

However, while this solved the compilation issue, it only got me to an issue in linking which may or may not be a result of the ifdef expedient ( and which may well have only to do with mangling): every C-based underpinning function went missing even though they were reliably found in the Mac build from the -L specified static libraries, such as FOO_int2str as shown here:

g++ -D_inline=__inline -shared -o /output/lib/libfoo_jni.dll   com_me_package_ClassName.o -L/some/number/of/such/things -lz -lzipfile
com_me_package_ClassName.o:com_me_package_ClassName.cpp:(.text+0x84) : undefined reference to `_imp__FOO_int2str'

I'm at a bit of a loss. Most of the few things I find via Google have fairly heavy contextual ties to other build environments (cygwin and Microsoft-supplied compilers, for instance). I have gcc and MinGW and would like to avoid answers that tie to things like dlltool or Cygwin, as the code I am working in has passed through many hands and has dark magicks (such as speech recognition) within it that are like caged lightning... the more I change the more risk I run that existing function on the mac platform will vanish.

I am a neophyte at makefile writing. That I have this building at all at the moment is a happy accident, as the code was extracted from a gigabytes-large corpus with a very heavy build gestalt targeting mobile rather than desktop platforms; a build context I knew I had to dump and which I've done so successfully (for the Mac at least). There's no going back there!

Thanks in advance for any advice with explicit command-line invocations to g++ (or gcc-like equivalent) that will get these functions to compile and link.

tone

You don't want to make your functions static because that gives them internal linkage. As the error message tells you, that's not compatible with the functions being exported. Your JNI functions need to have external linkage. This can be achieved by replacing static with extern. However, since external linkage is the default for functions you can simply remove the static linkage specifier and omit extern.

You also need to specify C linkage since you are compiling as C++ rather than C. Do this with extern "C". If you use the default C++ linkage then you end up with C++ name mangling which I suspect is the cause of your linker error.

So your code should be like this:

#include <jni.h> 

extern "C"
{

JNIEXPORT void JNICALL Java_com_me_package_ClassName_Moo
    (JNIEnv *env, jclass clazz) 
{
    printf("Moo!\n");
}

}