Create a cross-platform Java JNI build

I am writing a shell library for the C library (.so for Linux and .dll for Windows) using JNI. I am building my library on Linux Fedora 20 64bit with Oracle Java 1.7.0_45 64bit using g ++ (GCC) 4.8.2 64bit, and I am also building this library for windows using Oracle Java 1.7.0_45 32bit (for windows) and MinGW 32bit (i686-w64-mingw32-g ++ (GCC) 4.8.2) (I am creating a Windows library on Linux).

The Linux library works well, but when I use the Windows library on a computer running Windows XP sp3, I get a NullPointerException in the Java code when I try to print a byte array.

Here are the commands used to build the library:

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

This is part of my C ++ code:

#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;
    }
}

And this is part of my Java code:

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

structure(), ( Linux, Windows), openTable(), Linux. Windows System.out.println(== null); false, ByteBuffer buff = ByteBuffer.wrap(a); NullPointerException. , ?

+4

Source: https://habr.com/ru/post/1524480/


All Articles