JavaJNI跨平台构建
我正在使用JNI为C库(.so用于linux,.dll用于windows)编写一个包装器库。我使用g++(GCC)4.8.2 64位在linux Fedora 20 64位上使用Oracle Java 1.7.0_45 64位构建了我的库,我还使用Oracle Java 1.7.0_45 32位(用于windows)和MinGW 32位(i686-w64-mingw32-g++(GCC)4.8.2)为windows构建了这个库(我在linux上构建了windows库) Linux库工作得很好,但当我在带有WindowsXPSP3的机器上使用WindowsLibrary时,当我尝试打印字节数组时,java代码中会出现NullPointerException 以下是用于构建库的命令:JavaJNI跨平台构建,java,c++,java-native-interface,Java,C++,Java Native Interface,我正在使用JNI为C库(.so用于linux,.dll用于windows)编写一个包装器库。我使用g++(GCC)4.8.2 64位在linux Fedora 20 64位上使用Oracle Java 1.7.0_45 64位构建了我的库,我还使用Oracle Java 1.7.0_45 32位(用于windows)和MinGW 32位(i686-w64-mingw32-g++(GCC)4.8.2)为windows构建了这个库(我在linux上构建了windows库) Linux库工作得很好,但
g++ -Wall -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/linux" -fPIC -shared com_viking_micex_Micex.cpp -o libmicex.so
i686-w64-mingw32-g++ -Wall -Wl,--add-stdcall-alias -D_WIN32 -I"/media/OS/Program Files/Java/jdk1.7.0_45/include/" -I"/media/OS/Program Files/Java/jdk1.7.0_45/include/win32/" -shared com_viking_micex_Micex.cpp -o micex.dll
这是我的C++代码的一部分:
#define com_viking_micex_Micex_MTE_OK 0L
#ifdef _WIN32
#include <windows.h>
typedef HMODULE shared_lib;
typedef __int32 __int32_t;
#else
#include <dlfcn.h>
typedef void* shared_lib;
#endif
typedef struct TMTEMsg_
{
__int32_t DataLen;
char Data[1];
} TMTEMsg;
shared_lib load_lib(const char* lib_name) {
# ifdef _WIN32
return LoadLibraryA(lib_name);
# else //_WIN32
return dlopen(lib_name, RTLD_LAZY);
# endif //_WIN32
}
void* load_func(shared_lib lib, const char* func_name) {
# ifdef _WIN32
return (void *)GetProcAddress(lib, func_name);
# else //_WIN32
return dlsym(lib, func_name);
# endif //_WIN32
}
JNIEXPORT jbyteArray JNICALL Java_com_viking_micex_Micex_structure
(JNIEnv * env, jobject o, jobject pointer, jint connId, jint version) {
# ifdef _WIN32
shared_lib mtesrl = (HMODULE) env->GetDirectBufferAddress(pointer);
#else
shared_lib mtesrl = env->GetDirectBufferAddress(pointer);
#endif
typedef int (*importFunction)(int, int, TMTEMsg **);
importFunction Structure = (importFunction) load_func(mtesrl, "MTEStructureEx");
TMTEMsg *Msg;
int res = Structure(connId, version, &Msg);
char tmp[4];
tmp[3] = (res & 0xff);
tmp[2] = ((res & 0xff00) >> 8);
tmp[1] = ((res & 0xff0000) >> 16);
tmp[0] = ((res & 0xff000000) >> 24);
if (res != com_viking_micex_Micex_MTE_OK)
{
jbyteArray arr = env->NewByteArray(4);
env->SetByteArrayRegion(arr, 0, 4, (jbyte *) ((char*) (tmp)));
return arr;
}
else
{
jbyteArray arr = env->NewByteArray(Msg->DataLen + 4);
env->SetByteArrayRegion(arr, 0, 4, (jbyte *) ((char*) (tmp)));
env->SetByteArrayRegion(arr, 4, Msg->DataLen, (jbyte *) ((char*) (Msg->Data)));
return arr;
}
}
JNIEXPORT jbyteArray JNICALL Java_com_viking_micex_Micex_openTable
(JNIEnv * env, jobject o, jobject pointer, jint connId, jstring name, jstring params, jboolean complete) {
# ifdef _WIN32
shared_lib mtesrl = (HMODULE) env->GetDirectBufferAddress(pointer);
#else
shared_lib mtesrl = env->GetDirectBufferAddress(pointer);
#endif
typedef int (*importFunction)(int, char*, char*, int , TMTEMsg **);
importFunction OpenTable = (importFunction) load_func(mtesrl, "MTEOpenTable");
TMTEMsg *Msg;
char *params_ = (char *)env->GetStringUTFChars(params, 0);
char *name_ = (char *)env->GetStringUTFChars(name, 0);
int res = OpenTable(connId, name_, params_, complete, &Msg);
env->ReleaseStringUTFChars(params, params_);
env->ReleaseStringUTFChars(name, name_);
char tmp[4];
tmp[3] = (res & 0xff);
tmp[2] = ((res & 0xff00) >> 8);
tmp[1] = ((res & 0xff0000) >> 16);
tmp[0] = ((res & 0xff000000) >> 24);
if (res < com_viking_micex_Micex_MTE_OK)
{
jbyteArray arr = env->NewByteArray(4);
env->SetByteArrayRegion(arr, 0, 4, (jbyte *) ((char*) (tmp)));
return arr;
}
else
{
jbyteArray arr = env->NewByteArray(Msg->DataLen + 4);
env->SetByteArrayRegion(arr, 0, 4, (jbyte *) ((char*) (tmp)));
env->SetByteArrayRegion(arr, 4, Msg->DataLen, (jbyte *) ((char*) (Msg->Data)));
return arr;
}
}
首先我调用structure()方法,它工作得很好(在linux和windows上),然后我调用openTable(),它只在linux上工作。在windows系统上.out.println(a==null);打印错误,但ByteBuffer buff=ByteBuffer.wrap(a);抛出NullPointerException。
你知道为什么会这样吗
public class Micex {
private native byte[] structure(Object pointer, int connId, int version);
private native byte[] openTable(Object pointer, int connId, String name, String params, boolean complete);
public boolean structure(int version) {
ByteBuffer buff = ByteBuffer.wrap(structure(this.mtesrl, this.connId, version));
buff.order(ByteOrder.LITTLE_ENDIAN);
...
}
public boolean openTable(int key, TableName name, String params, boolean complete) {
if (openedTables.containsKey(key)) {
System.out.printf("Table \"%s\" with key \"%d\" is already opened\n", name.toString(), key);
return true;
}
byte [] a = openTable(this.mtesrl, this.connId, name.toString(), params, complete);
System.out.println(a == null);
ByteBuffer buff = ByteBuffer.wrap(a);
...
}
}