有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JNI:将对象从java返回C++,并将其传递回java

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

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

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

我在VisualStudio 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++调用java方法A和方法B,使用dll:< /p>

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呢?是否应该使用GETObjeCdfield创建一个C++结构体并将java对象字段映射到它?p>

共 (2) 个答案

  1. # 1 楼答案

    我不太明白为什么在代码中需要void**。如果想让界面不透明,只需使用void*。另外,不要忘记对返回的jobject调用NewGlobalRef()DeleteGlobalRef()——这将防止垃圾收集器破坏它:

    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));
    }
    
  2. # 2 楼答案

    有一个很棒的助手程序叫做javah.exe

    像编写代码一样编写代码,并执行javah.class。它将为您创建一个完全兼容的.h文件

    你会因此变得:

    public class Test {
    
        public class MyObject {
            private int no;
            private String status;
        }
    
        public class Callback {
            public void callback(MyObject afterCpp) {
    
            }
        }
    
        public native void register(Callback v, MyObject beforeCpp);
    }
    

    此标题:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class Test */
    
    #ifndef _Included_Test
    #define _Included_Test
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     Test
     * Method:    register
     * Signature: (LTest/Callback;LTest/MyObject;)V
     */
    JNIEXPORT void JNICALL Java_Test_register
      (JNIEnv *, jobject, jobject, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    只需调用callback第三个c++参数即可