从 JNI 返回 MPI::Request[] 类型并访问 Java 中的 Request 元素

Posted

技术标签:

【中文标题】从 JNI 返回 MPI::Request[] 类型并访问 Java 中的 Request 元素【英文标题】:Return MPI::Request[] type from JNI and access elements of Request in Java 【发布时间】:2015-02-21 04:52:50 【问题描述】:

我希望将 MPI::Request[] 类型从原生 C++ 函数返回给 Java(通过 JNI),然后从 Java 端访问 MPI::Request[] 数组中的元素。

JNIEXPORT jobjectArray JNICALL Java_mpiJNI_mpiTEST(JNIEnv *env, jobject obj) 
   MPI::Request req[8];
   return req;  // Error: Can't convert req to jobjectArray type

我知道的唯一接近的返回类型是 jobjectArrays,这不起作用。 Java 不知道 MPI::Request[] 类型是什么。

我不想使用 MPJ 或 MPIJava 之类的东西,因为我不知道 Java 中未来的 MPI 工作会有多少支持,并且我希望代码能够在许多集群更新和配置中持续存在。如果有人知道更多关于这件事的信息,我会很想知道更多。

【问题讨论】:

请告诉我们这与 c++ 有何关系 java 本机代码是用 C++ 编写的。 MPI 命令来自 C++,需要传回 Java。 【参考方案1】:

您需要返回一个 JNI 类型的 jobjectArray。 JNI 不会为您将该 req 指针转换为 jobjectArray。还要注意 java 如何布局对象数组和

首先,您在 C++ 堆栈上分配一个数组。这不是持久内存,因此当您的 JNI 方法返回时,req 指针将成为垃圾。因此,如果您想保留或分配本机数组存储,则需要使用“new”分配内存并拥有指向数组的持久指针。

我的建议是,不要返回和创建对象数组,而是将单个“指针”值返回给 java 到请求数组的开头,就像在 C++ 中所做的那样。

为了在 Java 对象中保留本地指针,典型的技巧是将指针转换为 java 'long' 原始类型,该类型的长度足以容纳大多数平台上的实际本地地址。将返回的“long”存储在您的 java 类中作为字段。

下次您需要访问本地 MPI::Request 数组时,您调用本地 java 方法并将存储为“long”的地址值传递给它,并在相应的 JNI 方法中转换 JNI jlong​​ 参数返回一个指针并将其类型转换为 MPI::Request *req ,因此您将在您的 java/jni 方法中成功创建请求,返回它,并将其存储在 java 类中,然后再次使用它在第二种方法中原生地使用 C++ 调用来创建/发送这些请求等等。

最后,由于您为 MPI::Result[] 动态分配了本机内存,请记住创建另一个 java 本机方法,该方法将再次将 long 值转换为指针并使用 C++ delete 语句释放内存,之后您没有不再需要那个数组。否则会出现内存泄漏。

以下是我将如何重写您的 JNI 方法:

JNIEXPORT jlong JNICALL Java_mpiJNI_mpiTEST(JNIEnv *env, jobject obj) 
   MPI::Request *req = new MPI::Request[8]; // Don't forget to release memory leater

   uintptr_t storage = (uintptr_t)ptr

   return (jlong) storage;

【讨论】:

这是对我的问题的一个非常好的答案!非常感谢!

以上是关于从 JNI 返回 MPI::Request[] 类型并访问 Java 中的 Request 元素的主要内容,如果未能解决你的问题,请参考以下文章

从异常返回的 JNI int 方法

如何释放 boost::mpi::request?

我对 boost::mpi::request 缺少啥?测试似乎改变了状态

JNI内形参从C代码中获取返回值并返回到Java层使用

如何将数组从 JNI 返回到 Java?

Android NDK- JNI 异常