JNI:将对象从Java返回到C++;,并将其传递回Java 我有一些java方法,我需要通过JNI从C++调用。我的JNI实现基于

JNI:将对象从Java返回到C++;,并将其传递回Java 我有一些java方法,我需要通过JNI从C++调用。我的JNI实现基于 ,java,c++,pointers,java-native-interface,Java,C++,Pointers,Java Native Interface,我的java项目中有两个java文件。一种是定义类,另一种包含C++调用的实际方法。 公共类MyObject{ 私有静态int-no; 私有静态LocalDateTime时间; 私有静态字符串状态; //接球手、二传手和投球手 } 公共类对象处理程序{ 公共静态MyObject objectReturnToC; 公共静态对象方法A(类型1 arg1、类型2 arg2、类型3 arg3){ objectReturnToC=新的MyObject(); //根据传入的参数设置returnObjec

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

公共类MyObject{
私有静态int-no;
私有静态LocalDateTime时间;
私有静态字符串状态;
//接球手、二传手和投球手
}
公共类对象处理程序{
公共静态MyObject objectReturnToC;
公共静态对象方法A(类型1 arg1、类型2 arg2、类型3 arg3){
objectReturnToC=新的MyObject();
//根据传入的参数设置returnObject中的字段
returnobjectreturntoc;
}
公共静态无效方法B(对象objectReturnedFromC){
//访问objectReturnedFromC中的字段,进行计算并存储在
}
}

我在VisualStudio 2010中创建了C++ DLL。有JVM.cpp、JVM.h、JavaCalls.h和JavaCalls.cpp

JavaCalls.h
#ifdef JAVACALLSDLL#u导出
#定义JAVACALLSDLL\u API\uu declspec(dllexport)
#否则
#定义JAVACALLSDLL\u API\uu declspec(dllimport)
#恩迪夫
命名空间Java调用
{
类JavaCalls
{
公众:
静态JAVACALLSDLL_API void*javaMethodA(类型1、类型2、类型3);
静态JAVACALLSDLL_API字符串toString(void**javaObject);
静态JAVACALLSDLL_API void javaMethodB(void**javaObject);
};
}
JavaCalls.cpp
名称空间调用
{
void*JavaCalls::javaMethodA(类型1 arg1、类型2 arg2、类型3 arg3)
{
//调用JVM
//查找类,方法ID
jobject javaObject=CallStaticObjectMethod(jMain,“methodA”,…);
返回javaObject;
}
void JavaCalls::javaMethodB(void**javaObject){
//调用JVM
//查找类,方法ID
CallStaticVoidMethod(jMain,methodB,…);
}
}
C++使用DLL调用Java methodA和methodB:

intmain()
{
void*a=JavaCalls::JavaCalls::javaMethodA(arg1、arg2、arg3);
//在数据库中执行其他操作和更新字段
JavaCalls::JavaCalls::javaMethodB(静态_cast(a));
}

显然,传递指针,希望它对C++是可用的,不起作用。但是我应该如何做才能将java对象保存在C++中,并在以后传递给java呢?如果我使用GETObjutfield?< /P> < P>创建一个C++结构体并将java对象字段映射到它,那么有一个很大的帮助程序叫做“代码> java.exe < /Cord>。p> 像编写代码一样编写代码,并对
.class
执行
javah
。它将为您创建一个完全兼容的
.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
/*不要编辑此文件-它是机器生成的*/
#包括
/*类测试的标题*/
#ifndef(包括)试验
#定义包含的测试
#ifdef_uucplusplus
外部“C”{
#恩迪夫
/*
*类别:测试
*方法:寄存器
*签名:(LTest/Callback;LTest/MyObject;)V
*/
JNIEXPORT void JNICALL Java\u测试\u寄存器
(JNIEnv*,jobject,jobject,jobject);
#ifdef_uucplusplus
}
#恩迪夫
#恩迪夫

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

我不太明白为什么您的代码中需要
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));
}
void*JavaCalls::javaMethodA(类型1 arg1、类型2 arg2、类型3 arg3)
{
jobject javaObject=CallStaticObjectMethod(jMain,“methodA”,…);
返回NewGlobalRef(jMain,javaObject);
}
void JavaCalls::javaMethodB(void*javaObject){
CallStaticVoidMethod(jMain,“methodB”,static_cast(javaObject));
}
//添加此方法-应在使用完对象后调用此方法
void JavaCalls::ReleaseObject(void*javaObject){
DeleteGlobalRef(jMain,static_cast(javaObject));
}

为什么要使用
void
指针?是什么阻止了你仅仅传递
jobject
s?使用<代码> Value**/COD>有什么意义?我认为VoIP指针是泛型指针,不知道我可以在C++ DLL中保持JOBJET并传递它。我一定要试试。稍后我还需要对其进行移植,以便C和FORTRAN可以调用Java方法。您认为即使使用C和FORTRAN,传递jobject也是一个不错的选择吗?问题是为什么需要这样调用jdbc?你可以直接从C++连接到DB,而且它可能更性能。我知道我可以直接从C++连接DB,但是我们已经决定不要求在所有用户计算机中安装OBDC驱动程序(它引起了很多的头痛和开销,请不要问我怎么办)。这就是为什么我需要通过JNI调用JDBC在C++中我认为这是通过java调用Java的C++语言的原因。我猜我错了。(java是java C++的一个新的对象),我认为Java对象传递给C++是不存在的(它有地址,但所有数据都不存在)。我把任务分配给C++还是用你的解决方案来处理空指针?Java将不理解从<代码> C <代码>或<代码> C++ >代码>的指针。code>Java是跨平台的,而
c++
32位的
64位的
。JNI是一个移植接口,而不是一个设计接口。这就是为什么
c++
-类型与
java
-类型完全不同的原因:您需要翻译它们。我可以在我的JavaMethodB末尾添加DeleteGlobalRef()吗?@wolf97084是的,当然可以,如果您不再需要对象的话。我不知道您要调用
JavaMethodB
或其他方法多少次,所以我编写了一个通用实现。我将所有void**更新为void*,现在尝试调用methodA返回的jobject上的toString。但是,从Totring()返回的字符串在C++调试器中始终是0x00亿。有spe吗