Problems compiling DLL using GCC on Windows

2019-08-30 13:21发布

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

1条回答
叼着烟拽天下
2楼-- · 2019-08-30 13:59

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");
}

}
查看更多
登录 后发表回答