当前位置: 首页 > 面试题库 >

如何在SWIG生成的Java绑定中转换为SWIGTYPE_p_void类型?

通学真
2023-03-14
问题内容

我正在为C库开发一些SWIG生成的Java绑定。该库包含采用类型参数的函数void *。在C端,这些通常会作为指向类型数组的指针传递float或转换intvoid *。在生成的Java绑定中,这导致采用类型参数的方法SWIGTYPE_p_void

在Java绑定中构造float / int数组的最佳方法是什么,以便可以将它们作为类型传递SWIGTYPE_p_void给这些方法?

目前,我在example.i文件中定义了一个辅助函数:

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

然后在Java方面执行以下操作:

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()对于我要支持的每种类型转换,我也需要在SWIG接口文件中添加一个etc。

有没有没有辅助功能的方法,而在Java端包含较少的额外代码来转换数据类型的方法?

更新(17/6/12): 为这个问题提供更多细节:我正在尝试做的是使用一组C函数,并带有原型int foo(const float *data, int N, const void *argv, float *result)并将它们映射到Java端的方法,在该方法中可以使用任意类型的数组作为传递argv。请注意,argvconst void *与不是void *


问题答案:

这个答案有一个替代方案,它与众不同,并且可以更自然地解决该问题,与您最初寻找的内容更接近。其他建议集中在增加重载(繁琐,手动)或使array_classes以一种或另一种方式实现通用接口。

它忽略的是在大多数情况下都Object非常适合void*Java。Java中Object的偶数[数组都是s。这意味着,如果您拥有SWIG映射void*Object它将接受您可能希望传递的任何数组作为输入。稍加注意和一些JNI,我们便可以获取指向该数组开始的指针,以传递给函数。显然,我们需要拒绝Object带有异常的non
array 。

我们仍然最终编写了一些(私有)辅助函数来安排对实际基础指针的提取,并在完成后将其释放,但是这种解决方案的好处是我们只需要执行一次,然后得到一个类型图,可以用于任何采用这样的数组的函数void*

我最终得到了以下用于该解决方案的SWIG界面:

%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在内部使用a
jlong表示指针。因此,对于每种数组类型,我们需要一个函数,该函数返回给定数组的指针,并释放另一个指针以释放它。它们是私有的,并且是模块类的一部分-除了模块,其他任何人都不需要知道它是如何工作的。

然后有两个函数Object使用和使用instanceof(难看,但是Java中的数组没有任何其他公共基数或接口,而泛型则无济于事)并调用正确的函数来获取/释放指针。

有了这些,只需两个类型图即可设置SWIG以将其用于所有void*arr参数。该jstype类型表指示夜风在使用Objectvoid*在这些情况下。javain类型映射安排一个临时局部变量来保存指针(位于中long),然后将其用于进行调用,并在调用成功或失败后进行清理。



 类似资料:
  • 错误CS0234:类型或命名空间名称com.sushi.hangover”中不存在。是否缺少程序集引用? 我有一个Android绑定项目,它有从多个接口继承的类,但这些接口没有生成,因此依赖于它们的所有公共类都无法绑定。 如您所见,该接口的没有设置为,因此不会生成C#代码,但是begin生成了依赖于该接口的公共类: 绑定在将接口名称从转换为时,可以识别接口。 是否有任何方法可以强制创建这些接口,而

  • 在的内部类中。 演员们在这里是怎么工作的?我在这里期待,因为我们要将一个纯超类对象转换为子类。

  • 问题内容: 我想在一个程序包中打印所有的类名,并在每个程序包中打印相应的属性及其数据类型。 在一个代码中,我能够以字符串形式获取类名。在另一个代码中,我可以使用以下方法获取属性及其数据类型 但是我想合并两个代码。由于在第一个代码中我以字符串的形式获得了类名,我无法使用,因为这里是类型。 因此,我需要一种将“ 类名”从类型转换为类型的方法。 我试过了,但是没有用。 问题答案: 确保是完全合格的类名,

  • 何时会生成绑定类,这里是ActivityMainBinding。我有编译时错误。“无法解析ActivityMainBinding”。 感谢任何帮助。谢谢

  • 我有一个界面 有几个像这样的类 这里重要的是,实现的所有类(如)都具有方法,但该方法不是接口的一部分。 现在,我需要将一些XML反序列化为一个Java对象。XML可以是任何实现类的对象,但是在反序列化之后,我将需要使用方法。 有什么简洁或优雅的方法来实现这一点吗? 我创建了另一个界面 并尝试创建它的实例 但在将XML强制转换为对象时会出现一个错误,该错误指出Bar的object类型的对象

  • 问题内容: 我是Java的新手,想知道double转换为int cast如何工作吗?我知道,只需将低32位转换为int就很容易了,但是将double(64位)转换为int(32位)呢?来自二进制的double中的那64位是Double- precision浮点格式(Mantissa),那么它如何在内部转换为int? 问题答案: 所有这些都记录在JLS的5.1.3节中。 第一步,将浮点数转换为lon