我如何转换成键入SWIGTYPE_p_void在痛饮生成的Java绑定? [英] How do I convert to type SWIGTYPE_p_void in SWIG generated Java bindings?

查看:487
本文介绍了我如何转换成键入SWIGTYPE_p_void在痛饮生成的Java绑定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发一个C库的痛饮生成的Java绑定。该库包含使用类型参数的函数无效* 。在C面,这些通常会作为指针传递给类型的数组浮动 INT 强制转换为无效* 。在生成的Java绑定,这将导致该采取类型参数的方法 SWIGTYPE_p_void

I am developing some SWIG-generated Java bindings for a C library. The library contains functions that take parameters of type void *. On the C side these would typically be passed as a pointer to an array of type float or int cast to void *. In the generated Java bindings, this results in methods that take parameters of type SWIGTYPE_p_void.

什么是构造float数组的最佳方法/在Java绑定整数,使他们能够为类型传递 SWIGTYPE_p_void 这些方法?

What is the best way to construct an array of floats/ints in the Java bindings so that they can be passed as type SWIGTYPE_p_void to these methods?

目前我定义我的example.i文件中的辅助函数:

At the moment I am defining a helper function in my example.i file:

void *floata_to_voidp(float f[])
{
    return (void *)f;
}

然后在Java端做这样的事情:

And then on the Java side doing something like this:

float foo[] = new float[2];
SWIGTYPE_p_void av = null;

// do something with foo

av = example.floata_to_voidp(foo);
example.myfunction(av);

这看起来相当丑,特别是我还需要一个 inta_to_voidp()等为每个类型转换我想支持我痛饮接口文件。

This seems rather ugly, especially as I would also need an inta_to_voidp() etc in my SWIG interface file for each type conversion I want to support.

有没有办法做到这一点无需辅助函数,涉及在Java端少额外的code,将数据类型?

Is there a way to do this without helper functions and involving less extra code on the Java side to convert data types?

UPDATE(17/6/12):可提供额外的细节问题:我想要做的就是采取了一系列C函数,用原型 INT富(常量浮点*数据,整数N,常量无效* argv的,浮动*结果),并将它们映射到Java端,其中任意类型的数组可以传递作为<$ C方法$ C>的argv 。需要注意的是的argv 常量无效* ,而不是无效*

UPDATE (17/6/12): to give additional detail to the question: what I'm trying to do is take a set of C functions, with prototype int foo(const float *data, int N, const void *argv, float *result) and map them to methods on the Java side where an array of arbitrary type can be passed in as argv. Note that argv is const void * and not void *.

推荐答案

有对这个答案的另一种选择,这是非常不同并给出了一个更自然的解决了这个问题,更接近你要找的最初。其他建议侧重于增加重载(单调,手动)或使 array_class ES实现共同的接口拉上。

There's an alternative to this answer, it's very different and gives a more natural solution to this problem, closer to what you were looking for originally. The other suggestions were focused on adding overloads (tedious, manual) or making the array_classes implement a common interface one way or another.

什么它忽略的是,对象一个很好的匹配无效* Java中的大部分时间。在Java中,甚至阵列对象取值。这意味着如果你有SWIG地图无效* 对象它会接受作为输入你可能想传递任何阵列在随着一点关怀和一些JNI我们就可以得到一个指向该数组的开始在传递给函数。很显然,我们需要拒绝,虽然非阵列对象 s的一个例外。

What it overlooks is that Object is a good match for void* in Java most of the time. Even arrays in Java are Objects. This means if you have SWIG map void* to Object it'll accept as inputs any arrays you might want to pass in. With a bit of care and some JNI we can then get a pointer to the start of that array to pass in to the function. Obviously we need to reject non array Objects with an exception though.

我们仍可以写一些(专用)辅助函数来安排真正的根本指针的提取和释放完成后,但这个解决方案的好处是,我们只有这样做一次,然后我们结束了可用于内搭数组作为无效* 是这样的。

We still end up writing some (private) helper functions to arrange extraction of the real underlying pointer and release it when done, but the nice thing about this solution is that we only have to do this once and then we end up with a typemap that can be used for any functions which take an array as void* like this.

我结束了该解决方案如下痛饮接口:

I ended up with the following SWIG interface for this solution:

%module test

%{
#include <stdint.h>

void foo(void *in) {
  printf("%p, %d, %g\n", in, *(jint*)in, *(jdouble*)in);
}
%}

%typemap(in,numinputs=0) JNIEnv *env "$1 = jenv;"

%javamethodmodifiers arr2voidd "private";
%javamethodmodifiers arr2voidi "private";
%javamethodmodifiers freearrd "private";
%javamethodmodifiers freearri "private";
%inline %{
jlong arr2voidd(JNIEnv *env, jdoubleArray arr) {
  void *ptr = (*env)->GetDoubleArrayElements(env, arr, NULL);
  return (intptr_t)ptr;
}

void freearrd(JNIEnv *env, jdoubleArray arr, jlong map) {
  void *ptr = 0;
  ptr = *(void **)&map;
  (*env)->ReleaseDoubleArrayElements(env, arr, ptr, JNI_ABORT);
}

jlong arr2voidi(JNIEnv *env, jintArray arr) {
  void *ptr = (*env)->GetIntArrayElements(env, arr, NULL);
  return (intptr_t)ptr;
}

void freearri(JNIEnv *env, jintArray arr, jlong map) {
  void *ptr = 0;
  ptr = *(void **)&map;
  (*env)->ReleaseIntArrayElements(env, arr, ptr, JNI_ABORT);
}
%}


%pragma(java) modulecode=%{
  private static long arrPtr(Object o) {
    if (o instanceof double[]) {
      return arr2voidd((double[])o);
    }
    else if (o instanceof int[]) {
      return arr2voidi((int[])o);
    }
    throw new IllegalArgumentException();
  }

  private static void freeArrPtr(Object o, long addr) {
    if (o instanceof double[]) {
      freearrd((double[])o, addr);
      return;
    }
    else if (o instanceof int[]) {
      freearri((int[])o, addr);
      return;
    }
    throw new IllegalArgumentException();
  }
%}

%typemap(jstype) void *arr "Object"
%typemap(javain,pre="    long tmp$javainput = arrPtr($javainput);",post="      freeArrPtr($javainput, tmp$javainput);") void *arr "tmp$javainput"

void foo(void *arr);

这是实现两个数组类型,有一个小数量有限,你可以使用片段或宏,以帮助这一点。内部SWIG使用 jlong​​ 重新present指针。因此,对于每个数组类型我们需要返回给定阵列和另一个释放它的指针的函数。这些都是私人和模块类的一部分 - 其他人比模块需要知道如何工作的。

This implements it for two array types, there's a small finite number and you could use fragments or macros to help with this too. Internally SWIG uses a jlong to represent pointers. So for each array type we need a function that returns a pointer for a given array and another one to release it. These are private and part of the module class - nobody other than the module needs to know how this works.

有那么两个函数取对象,并使用的instanceof (丑,但在Java数组不有任何其他的公共基础或接口和泛型没有帮助),并调用正确的函数来获取/释放的指针。

There's then two functions which take the Object and use instanceof (ugly, but arrays in Java don't have any other common base or interface and generics don't help) and call the correct function to get/release the pointers.

使用这些那么它只有两个typemaps设立痛饮到所有使用它的无效*改编参数。该jstype类型映射指示痛饮在这些情况下,使用对象无效* 。该javain类型映射安排一个临时局部变量来保存指针(在),然后它被用来拨打电话,并进行清理一次通话有成功或失败。

With these then it's just two typemaps to set up SWIG to use it for all void *arr arguments. The jstype typemap instructs SWIG to use Object for void* in these cases. The javain typemap arranges for a temporary local variable to hold the pointer (in a long) and then for it to be used to make the call and to be cleaned up once the call has succeed or failed.

这篇关于我如何转换成键入SWIGTYPE_p_void在痛饮生成的Java绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆