[英]How to send a 2D array from C++ and edit the values in Java and send back to C++ in 2D array via JNI
根據主題,我有一個名為cells
的2D數組,其中包含C ++中的某些值。
我想將此2D數組發送到我的Java文件中,它將替換其中的一些值。 我有什么方法可以用Java從C ++中“接收”數組嗎?
目前,我可以使用C ++從Java打印內容。 我的源代碼如下:
C ++源代碼:
//JNI
#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <vector>
//jvm
JavaVMOption options[1];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
long status;
jclass cls;
jmethodID mid;
typedef std::vector<std::vector<int>> IntMatrix;
IntMatrix cells;
//fn header
template<std::size_t OuterDim, std::size_t InnerDim>
jobjectArray to_java(JNIEnv *env, int(&arr)[OuterDim][InnerDim]);
std::vector<std::vector<int> > from_java(JNIEnv *env, jobjectArray arr);
jobjectArray v2jObs(IntMatrix v2D);
int main(){
cells = { { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }, { 0, 1, 1, 1, 1, 1, 0, 1, 0, 1 }, { 0, 1, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1 }, { 0, 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 1, 1, 1, 0, 1, 0, 1, 0, 1 }, { 0, 1, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1 }, { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
options[0].optionString = "-Djava.class.path=C:\\Users\\Downloads\\ConsoleApplication2\\ConsoleApplication2";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;
status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
//int cells[10][10]; // my 2d array
//for (int i = 0; i < 10; i++){
// for (int j = 0; j < 10; j++){
// cells[i][j] = 1;
// }
//}
if (status != JNI_ERR){
cls = env->FindClass("Sample2");
if (cls != 0){
mid = env->GetStaticMethodID(cls, "intArrayMethod", "([[I)[[I");
if (mid != 0){
jobjectArray java_cells = static_cast<jobjectArray>(env->CallStaticObjectMethod(cls, mid, v2jObs(cells)));
std::vector<std::vector<int> > cpp_cells = from_java(env, java_cells);
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
printf("%d", cpp_cells[i][j]);
}
}
}
}
jvm->DestroyJavaVM();
return 0;
}
else{
return 1;
}
}
// The template bit here is just to pick the array dimensions from the array
// itself; you could also pass in a pointer and the dimensions.
template<std::size_t OuterDim, std::size_t InnerDim>
jobjectArray to_java(JNIEnv *env, int(&arr)[OuterDim][InnerDim]) {
// We allocate the int array first
jintArray inner = env->NewIntArray(InnerDim);
// to have an easy way to get its class when building the outer array
jobjectArray outer = env->NewObjectArray(OuterDim, env->GetObjectClass(inner), 0);
// Buffer to bring the integers in a format that JNI understands (jint
// instead of int). This step is unnecessary if jint is just a typedef for
// int, but on OP's platform this appears to not be the case.
std::vector<jint> buffer;
for (std::size_t i = 0; i < OuterDim; ++i) {
// Put the data into the buffer, converting them to jint in the process
buffer.assign(arr[i], arr[i] + InnerDim);
// then fill that array with data from the input
env->SetIntArrayRegion(inner, 0, InnerDim, &buffer[0]);
// and put it into the outer array
env->SetObjectArrayElement(outer, i, inner);
if (i + 1 != OuterDim) {
// if required, allocate a new inner array for the next iteration.
inner = env->NewIntArray(InnerDim);
}
}
return outer;
}
// Note that this function does not return an array but a vector of vectors
// because 2-dimensional Java arrays need not be rectangular and have
// dynamic size. It is not generally practical to map them to C++ arrays.
std::vector<std::vector<int> > from_java(JNIEnv *env, jobjectArray arr) {
// always on the lookout for null pointers. Everything we get from Java
// can be null.
jsize OuterDim = arr ? env->GetArrayLength(arr) : 0;
std::vector<std::vector<int> > result(OuterDim);
for (jsize i = 0; i < OuterDim; ++i) {
jintArray inner = static_cast<jintArray>(env->GetObjectArrayElement(arr, i));
// again: null pointer check
if (inner) {
// Get the inner array length here. It needn't be the same for all
// inner arrays.
jsize InnerDim = env->GetArrayLength(inner);
result[i].resize(InnerDim);
jint *data = env->GetIntArrayElements(inner, 0);
std::copy(data, data + InnerDim, result[i].begin());
env->ReleaseIntArrayElements(inner, data, 0);
}
}
return result;
}
jobjectArray v2jObs(IntMatrix v2D){
int y = v2D.size();
int x = v2D[0].size();
jint **arr2D = new jint*[y];
jintArray inner = env->NewIntArray(x);
jobjectArray outer = env->NewObjectArray(y, env->GetObjectClass(inner), 0);
for (unsigned i = 0; (i < y); i++)
{
arr2D[i] = new jint[x];
for (unsigned j = 0; (j < x); j++)
{
arr2D[i][j] = v2D[i][j];
}
env->SetIntArrayRegion(inner, 0, x, arr2D[i]);
env->SetObjectArrayElement(outer, i, inner);
}
return outer;
}
IntMatrix jObs2v(jobjectArray arr2D){
int y = env->GetArrayLength(arr2D);
//int x = env->GetObjectLength(env->GetObjectArrayElement(arr2D, 0));
IntMatrix result(y);
return result;
}
Java的:
public class Sample2{
public static void main(String []args){
//
}
public static int[][] intArrayMethod(int[][] n){
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
n[i][j] = 2;
}
}
return n;
}
}
我是否必須在Java程序中包含一些代碼來“接收”來自C ++的cell
2D數組值? 我整夜都在搜索,但無法正常工作。 請幫忙 !!!
我將類重命名為SampleSO
,使Array為3x3,並使intArrayMethod
方法的值是每個單元格的兩倍。 為簡單起見,我沒有使用您的v2jObs
函數和您的IntMatrix
類型。
我復制/粘貼了兩個C ++函數to_java
和from_java
, 嚴格未經修改 (在下面省略)
java類:
public class SampleSO{
public static void main(String []args){}
public static int[][] intArrayMethod(int[][] n){
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
n[i][j] *= 2;
}
}
return n;
}
}
C ++源代碼(沒有to_java
和from_java
)
#include <jni.h>
#include <cstring>
#include <vector>
int wmain( int argc, wchar_t * argv[] ) {
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=C:/Users/manuel/Documents/Visual Studio 2010/Projects/JavaArray";
JavaVMInitArgs vm_args;
memset( &vm_args, 0, sizeof( vm_args ) );
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;
JavaVM *jvm;
JNIEnv *env;
jint status = JNI_CreateJavaVM( &jvm, (void**)&env, &vm_args );
printf( "JNI_CreateJavaVM said %d\n", status );
if ( status != JNI_ERR ) {
jclass cls = env->FindClass( "SampleSO" );
if ( cls != nullptr ) {
printf( "Class Found\n" );
jmethodID mid = env->GetStaticMethodID( cls, "intArrayMethod", "([[I)[[I");
if ( mid != nullptr ) {
printf( "Method Found\n" );
int Array[3][3] = { { 1, 1, 1 }, { 2, 2, 2 }, { 3, 3, 3 }, };
jobjectArray java_cells = static_cast<jobjectArray>( env->CallStaticObjectMethod( cls, mid, to_java( env, Array ) ) );
printf( "Method Called\n" );
std::vector<std::vector<int> > Result = from_java( env, java_cells );
printf( "Dumping Result:\n" );
for ( size_t RowIndex = 0; RowIndex < Result.size(); ++RowIndex ) {
for ( size_t ColIndex = 0; ColIndex < Result[ RowIndex ].size(); ++ColIndex ) {
printf( "%d ", Result[ RowIndex ][ ColIndex ] );
} // end for
printf( "\n" );
} // end for
} // endif
} // endif
} // endif
return 0;
} // wmain
結果:
請注意:
ExceptionCheck
,或ExceptionOccurred
,然后ExceptionClear
在C ++中,JNI調用之后。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.