我有一些Java方法需要通过JNI从C++调用。我的JNI实现基于
Is it possible to make a Java JNI which calls jdbc?

我的Java项目中有两个Java文件。一种是定义一个类,另一种包含c++将调用的实际方法。


public class MyObject {
    private static int no;
    private static LocalDateTime time;
    private static String status;
    // getters, setters and toString
}

public class ObjectHandler {
    public static MyObject objectReturnToC;

    public static Object methodA (type1 arg1, type2 arg2, type3 arg3) {
        objectReturnToC = new MyObject();
        // setting fields in returnObject according to passed-in parameters
        return objectReturnToC;
    }
    public static void methodB(Object objectReturnedFromC) {
        // access fields in objectReturnedFromC, do computation and store in
    }
}

我在Visual Studio 2010中创建了C++ DLL。其中有JVM.cpp,JVM.h,JavaCalls.h和JavaCalls.cpp。

JavaCalls.h

#ifdef JAVACALLSDLL_EXPORTS
#define JAVACALLSDLL_API __declspec(dllexport)
#else
#define JAVACALLSDLL_API __declspec(dllimport)
#endif

namespace JavaCalls
{
    class JavaCalls
    {
    public:
        static JAVACALLSDLL_API void *javaMethodA(type1, type2, type3);
        static JAVACALLSDLL_API string toString(void **javaObject);
        static JAVACALLSDLL_API void javaMethodB(void **javaObject);
    };
}

JavaCalls.cpp

namespace JavaCalls
{
    void *JavaCalls::javaMethodA(type1 arg1, type2 arg2, type3 arg3)
    {
        // invoke JVM
        // Find class, methodID
        jobject javaObject = CallStaticObjectMethod(jMain, "methodA",...);
        return javaObject;
    }
    void JavaCalls::javaMethodB(void** javaObject) {
        // invoke JVM
        // Find class, methodID
        CallStaticVoidMethod(jMain, "methodB",...);
    }
}

C++使用DLL调用Java methodA和methodB:

int main()
{
    void* a = JavaCalls::JavaCalls::javaMethodA(arg1, arg2, arg3);
    // doing other stuff and updating fields in a
    JavaCalls::JavaCalls::javaMethodB(static_cast<void**>(a));
}

显然,传递指针并希望该指针可用于C++是行不通的。但是,我应该怎么做才能将Java对象保留在C++中,并在以后将其传递回Java?我应该创建一个C++结构并使用GetObjectField将Java Object字段映射到其中吗?

最佳答案

我不太明白为什么您的代码中需要void**。如果要使界面不透明,只需使用void*即可。同样不要忘记在返回的NewGlobalRef()上调用DeleteGlobalRef()jobject-这将防止垃圾回收器对其破坏:

void *JavaCalls::javaMethodA(type1 arg1, type2 arg2, type3 arg3)
{
    jobject javaObject = CallStaticObjectMethod(jMain, "methodA",...);
    return NewGlobalRef(jMain, javaObject);
}

void JavaCalls::javaMethodB(void* javaObject) {
     CallStaticVoidMethod(jMain, "methodB", static_cast<jobject>(javaObject));
}

// add this method - it should be called when you finish using the object
void JavaCalls::ReleaseObject(void* javaObject) {
     DeleteGlobalRef(jMain, static_cast<jobject>(javaObject));
}

10-06 13:19