简体   繁体   English

如何使用Swig将数组(java中的long数组)从Java传递给C ++

[英]How to pass array(array of long in java) from Java to C++ using Swig

I have sample .h file like below: 我有样本.h文件,如下所示:

class Test
{
public:
       void SelectValues(long long values[])
};

I used SWIG and created JNI interface from below .i file 我使用SWIG并从.i文件下面创建了JNI接口

%module MyLib
%include "carrays.i"
%array_functions(long long, long_long_array )


%{
  #include "Test.h"
%}

/* Let's just grab the original header file here */
%include <windows.i> /*This line is used for calling conventions*/ 
% include "Test.h"

When I create Java method it creates like: 当我创建Java方法时,它创建如下:

public void SelectValues(SWIGTYPE_p_long_long includeKeys)

Also for JNI file it is taking argument as jlongArray but taking simple jlong only. 同样对于JNI文件,它将参数作为jlongArray但仅使用简单的jlong Due to this issue I cannot create array of long like long[]={1L,2L} and pass it to above Java method to call appropriate JNI method. 由于这个问题,我无法像long[]={1L,2L}那样创建长数组,并将其传递给Java方法以上以调用适当的JNI方法。

I want SWIG to generate interface in such a way that I can pass above mentioned array to my C++ method. 我希望SWIG以这样的方式生成接口,我可以将上面提到的数组传递给我的C ++方法。

I have read this question , but it didn't help me see how to pass an array from Java to C++. 我已经阅读了这个问题 ,但它没有帮助我看到如何将数组从Java传递给C ++。

What you've done here with array_functions is correct and usable, but it's focused on wrapping the C++ code directly, and it won't be using an underlying Java array. 你在这里使用array_functions是正确和可用的,但是它专注于直接包装C ++代码,并且它不会使用底层Java数组。 You can use it with something like: 您可以使用以下内容:

SWIGTYPE_p_long_long array = MyLib.new_long_long_array(100); // new array with 100 elements.
for (int i = 0; i < 100; ++i) {
  long_long_array_setitem(array, i, i);
}
new Test().SelectValues(array);

where array is just a proxy to a "real" C++ chunk of memory that you can read/write from on the Java side and pass to wrapped functions. 其中array只是一个“真正的”C ++内存块的代理,您可以在Java端读取/写入并传递给包装函数。

I'm guessing from your question that you're interested in making this feel more "natural" on the Java side. 我猜你的问题是你有兴趣让这种感觉在Java方面更“自然”。 SWIG also provides array_class which wraps an array similarly, but as a proper object rather than a collection of static functions. SWIG还提供了array_class ,它类似地包装数组,但是作为一个正确的对象而不是静态函数的集合。 For example if you changed your interface file to use array_class(long long, LongLongArray) instead of array_functions you can do: 例如,如果您将接口文件更改为使用array_class(long long, LongLongArray)而不是array_functions ,则可以执行以下操作:

LongLongArray array = new LongLongArray(100);
for (int i = 0; i < 100; ++i) {
   array.setitem(i,i); 
}
new Test().SelectValues(array.cast());

You can actually make SWIG do more than that with a few typemaps if you want to. 实际上,如果您愿意,可以使用少量类型映射使SWIG执行更多操作。 Your example class doesn't take a length in SelectValues so I'm assuming you're 0 terminating the array although you can equally well pass the length in with a few simple changes. 你的示例类在SelectValues中没有花费一个长度,所以我假设你是0终止数组,尽管你可以通过几个简单的更改同样很好地传递长度。

(For convenience I %inline d your class to reduce the number of files and added a dummy implementation of it for testing) (为方便起见,我将你的类%inline到减少文件数量并为测试添加了一个虚拟实现)

%module MyLib

%{
#include <iostream>
%}

%typemap(jtype) long long values[] "long[]"
%typemap(jstype) long long values[] "long[]"
%typemap(javain) long long values[] "$javainput"
%typemap(jni) long long values[] "jlongArray"
%typemap(in) long long values[] {
  jboolean isCopy;
  $1 = JCALL2(GetLongArrayElements, jenv, $input, &isCopy);
}

%inline %{
class Test
{
public:
  void SelectValues(long long values[]) {
    while (*values) {
      std::cout << *values++ << "\n";
    }
  }
};
%}

Here we said that both the proxy class SWIG generates and the JNI class it generates are going to be working with long[] , ie a Java array. 这里我们说代理类SWIG生成它和它生成的JNI类将使用long[] ,即Java数组。 We don't need to do anything in the Java Proxy to Java JNI conversion, so the javain typemap is just a straight pass through. 我们不需要在Java代理到Java JNI转换中执行任何操作,因此javain只是直接传递。 On the C++ side of the JNI that's a jlongArray , which we also specified in another typemap. 在JNI的C ++端,这是一个jlongArray ,我们也在另一个typemap中指定了它。

We then need an in typemap to arrange converting from jlongArray to long long[] in the C++ side - there's a single JNI call for that and we don't care if it's a copy or the actual memory from the JVM that we end up using. 然后我们需要一个in typemap来安排从Clong方面的jlong​​Array到long long[]转换 - 对此有一个JNI调用,我们不关心它是来自JVM的副本还是我们最终使用的实际内存。 (You might care if you wanted to modify the results and make it visible back inside Java for example) (您可能会关心是否要修改结果并将其显示在Java中,例如)

I tested this with: 我测试了这个:

public class run {
  public static void main(String[] argv) {
    System.loadLibrary("mylib");
    long arr[] = {100,99,1,0}; // Terminate with 0!
    new Test().SelectValues(arr);
  }
}

Which did exactly as you'd hope. 这完全按照你的意愿行事。

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

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