简体   繁体   English

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

[英]JNI: return an object from Java to C++, and pass it back to Java

I have some Java methods that I need to call from C++ via JNI. 我有一些Java方法需要通过JNI从C ++调用。 My JNI implementation is based on 我的JNI实现基于
Is it possible to make a Java JNI which calls jdbc? 是否可以创建一个调用jdbc的Java JNI?

There are two java files in my Java project. 我的Java项目中有两个java文件。 One is to define a class, and the other one contains the actual methods that c++ will call. 一种是定义一个类,另一种是包含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
    }
}

I created C++ DLL in Visual Studio 2010. There's JVM.cpp, JVM.h, JavaCalls.h, and JavaCalls.cpp 我在Visual Studio 2010中创建了C ++ DLL。有JVM.cpp,JVM.h,JavaCalls.h和JavaCalls.cpp

JavaCalls.h 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 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++ calling Java methodA and methodB using DLL: C ++使用DLL调用Java方法A和方法B:

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

Obviously, passing pointer, wishing it would be available to C++ is not working. 显然,传递指针,希望它可用于C ++是行不通的。 But what should I do to keep the Java Object in C++ and pass it back to Java later? 但是我该怎么做才能将Java Object保存在C ++中并稍后将其传递给Java呢? Should I create a C++ struct and map Java Object field into it using GetObjectField? 我应该使用GetObjectField创建C ++结构并将Java Object字段映射到其中吗?

I don't quite understand why you need void** in your code. 我不太明白你的代码中为什么需要void** If you want to make the interface opaque, just use void* . 如果要使界面不透明,只需使用void* Also don't forget to call NewGlobalRef() and DeleteGlobalRef() on the returned jobject - this will prevent its destruction by garbage collector: 另外,不要忘记在返回的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));
}

There is a great helper program called javah.exe . 有一个很棒的帮助程序叫做javah.exe

Write your code like you like to code and execute javah to the .class . 像编写代码一样编写代码并将javah执行到.class It will create a full compatible .h file for you. 它将为您创建一个完全兼容的.h文件。

You will become for this: 你会成为这样的:

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

This header: 这个标题:

/* 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

You simply have to call callback to the 3rd c++-parameter. 您只需要调用callback到第3个c ++ - 参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM