将简单的 java 数组传递给原始的 c-array swig

Posted

技术标签:

【中文标题】将简单的 java 数组传递给原始的 c-array swig【英文标题】:pass simple java array to primitive c-array swig 【发布时间】:2016-10-07 11:03:01 【问题描述】:

我想将一个简单的 java 数组传递给 c。

目前我使用以下 .i 文件进行操作。

%module example

%include "arrays_java.i"
%include "example.h"
%
#include "example.h"
%

带有arrays_java.i 标头的java 数组被接受。 但它制作了数组的完整副本,这对我来说太慢了。 我尝试使用这些构建类型映射,我可以使用 GetDoubleArray 函数来获取 java 数组的指针。 在我使用 swig 之前,我使用 JNI GetDoubleArrayElements 构建了自己的包装器,这要快得多。

您可以在下面看到我尝试在类型映射中使用 Jni 函数。

%typemap(jtype) (double *values, int lenght) "double[]"
%typemap(jstype) (double *values, int lenght) "double[]"
%typemap(javain) (double *values, int lenght) "$javainput"
%typemap(jni) (double *values, int lenght) "jdoubleArray"
%typemap(in) (double *values, int lenght) 

    $1 = (double *)JCALL2(GetDoubleArrayElements, jenv, $input, NULL);
    $2 = (int)    JCALL1(GetArrayLength,       jenv, $input);
 

 %apply (double * DOUBLE, int LENGTH)    (double * doubleArray, long len) ;

但是 swig 只为我构建了一个我应该使用的 javaclass (SWIGTYPE_p_double)。 我只想传递一个简单的java数组并在c中使用这个java数组指针。

希望你能帮助我,谢谢

编辑:

在这里你可以看到我完整的 .i 文件。我纠正了长度失败。同样的问题

%module exampleModule
%include "std_string.i"
%include "std_vector.i"
%include "arrays_java.i"
#include <string>
#include <vector>





%template(nativeDoubleVector) std::vector<double>;



%typemap(jtype) (double *values, int length) "double[]"
%typemap(jstype) (double *values, int length) "double[]"
%typemap(javain) (double *values, int length) "$javainput"
%typemap(jni) (double *values, int length) "jdoubleArray"
%typemap(in) (double *values, int length) 

   $1 = (double *)JCALL2(GetDoubleArrayElements, jenv, $input, NULL);
   $2 = (int)    JCALL1(GetArrayLength,       jenv, $input);


%apply (double * values, int length)    (double * doubleArray, long len) ;




/* Let's just grab the original header file here */
%include "example.h"
%
  #include "example"
%

和 .h 文件

class example

public:
    example(int width, int height);
    ~example();
    test(double *values, int length);
 ;

我可以看到 -Wall 输出吗?我试了一下,但我在android studio终端中没有输出

【问题讨论】:

您对“长度”一词的拼写似乎有误,但还有更多问题。使用 -Wall 参数运行 SWIG 并注意我很确定您会在 %apply 上看到的警告。您能否向我们展示 example.h 和您的 .i 文件以及您的类型映射? 我编辑了我的帖子。谢谢解答 【参考方案1】:

我得到了前半部分的解决方案。

//java float[] in c float arr
%typemap(jstype) double[] "double[]"
%typemap(jtype) double[] "double[]"
%typemap(jni) double[] "jdoubleArray"
%typemap(javain) double[] "$javainput"
%typemap(in) double[] 
    $1 = JCALL2(GetDoubleArrayElements, jenv, $input, NULL);

这段代码允许我使用 java 数组而不需要它的副本。 但是我不能在 c 端更改值,而 java 端知道它。 Java 端有旧值。

我知道错了。在 wrap.cpp 中缺少 ReleasDoubleArrayElements 函数。 当我将它插入 wrap.cpp 时,一切都很好。下面你可以看到 swig 生成的 wrap.cpp。

SWIGEXPORT void JNICALL      Java_com_example_glm_ndk_1swig_1example_exampleJNI_Circle_1testfunktion(JNIEnv   *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jfloatArray jarg2, jint jarg3) 
   Circle *arg1 = (Circle *) 0 ;
   float *arg2 ;
   int arg3 ;

   (void)jenv;
   (void)jcls;
   (void)jarg1_;
   arg1 = *(Circle **)&jarg1; 
   
     arg2 = jenv->GetFloatArrayElements(jarg2, NULL);
   
   arg3 = (int)jarg3; 
   (arg1)->testfunktion(arg2,arg3);
   jenv->ReleaseFloatArrayElements(jarg2, arg2, NULL);//insert manually

但是我必须告诉 swig 插入这个函数吗?

编辑:

我得到了解决方案。谢谢柔印。你帮我解决了另一个问题。 python arg out 我必须使用 %typemap(argout)。您可以在下面看到适合我的解决方案。

%typemap(jstype) double[] "double[]"
%typemap(jtype) double[] "double[]"
%typemap(jni) double[] "jdoubleArray"
%typemap(javain) double[] "$javainput"
%typemap(in) double[] 
     $1 = JCALL2(GetDoubleArrayElements, jenv, $input, NULL);

%typemap(argout) double[]
    JCALL3(ReleaseDoubleArrayElements,jenv, $input, $1, 0);

这比将数组复制到 c 快得多。

【讨论】:

以上是关于将简单的 java 数组传递给原始的 c-array swig的主要内容,如果未能解决你的问题,请参考以下文章

将向量数组作为函数参数传递以更改原始值

将结构传递给cupy中的原始内核

从 C++ 将字节数组传递给 lua 脚本方法

可以将 Java 数组传递给采用数组的 C/C++ 函数吗?

JNI维数组:将二维数组从java传递给c

Java中的高性能原始数组构建器