根据主题,我有一个名为cells
的二维数组,其中包含一些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;
}
爪哇:
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程序中包含一些代码来接收&#34;接收&#34;来自C ++的cell
2D数组值?我整夜都在搜索,但无法正常工作。请帮忙!!!
答案 0 :(得分:0)
我将类重命名为SampleSO
,使数组为3x3,并使intArrayMethod
方法成为每个单元格值的两倍。为简单起见,我没有使用您的v2jObs
函数和IntMatrix
类型。
我复制/粘贴了两个C ++函数to_java
和from_java
,严格未修改(下面省略)
java Class:
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
。