- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在为 C 库开发一些 SWIG 生成的 Java 绑定(bind)。该库包含采用 void *
类型参数的函数。在 C 端,这些通常作为指向 float
类型数组或 int
类型转换为 void *
的指针传递。在生成的 Java 绑定(bind)中,这会导致采用 SWIGTYPE_p_void
类型参数的方法。
在 Java 绑定(bind)中构造 float /整数数组以便将它们作为类型 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);
这看起来相当丑陋,尤其是因为我还需要在我的 SWIG 接口(interface)文件中为我想要支持的每种类型转换添加 inta_to_voidp()
等。
有没有一种方法可以在没有辅助函数的情况下执行此操作,并且在 Java 端涉及较少的额外代码来转换数据类型?
更新(2012 年 6 月 17 日): 为问题提供更多细节:我想做的是采用一组 C 函数,原型(prototype)为 int foo( const float *data, int N, const void *argv, float *result)
并将它们映射到 Java 端的方法,其中可以将任意类型的数组作为 argv
传入。请注意,argv
是 const void *
而不是 void *
。
最佳答案
this answer 有一个替代方案,它非常不同,并且为这个问题提供了更自然的解决方案,更接近您最初寻找的内容。其他建议侧重于添加重载(繁琐,手动)或使 array_class
es 以某种方式实现通用接口(interface)。
它忽略的是 Object
在大多数情况下与 Java 中的 void*
非常匹配。连arrays in Java are Object
s .这意味着如果你有 SWIG map void*
到 Object
它会接受你可能想要传入的任何数组作为输入。稍微小心一点和一些 JNI 我们可以然后获取指向该数组开头的指针以传递给函数。显然,我们需要拒绝非数组 Object
,但有一个异常(exception)。
我们最终还是写了一些(私有(private)的)辅助函数来安排提取真正的底层指针并在完成后释放它,但是这个解决方案的好处是我们只需要这样做一次然后我们就结束了一个类型映射,可用于像这样将数组作为 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 **)↦
(*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 **)↦
(*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
来表示指针。因此,对于每种数组类型,我们都需要一个函数来返回给定数组的指针和另一个函数来释放它。这些是私有(private)的并且是模块类的一部分 - 除了模块之外没有人需要知道它是如何工作的。
然后有两个函数接受 Object
并使用 instanceof
(丑陋,但 Java 中的数组没有任何其他公共(public)基础或接口(interface),泛型也没有帮助)并调用正确的函数来获取/释放指针。
有了这些,只需两个类型映射即可设置 SWIG 以将其用于所有 void *arr
参数。在这些情况下,jstype 类型映射指示 SWIG 使用 Object
作为 void*
。 javain 类型映射安排一个临时局部变量来保存指针(在 long
中),然后用于进行调用并在调用成功或失败后清除。
关于java - 如何在 SWIG 生成的 Java 绑定(bind)中转换为 SWIGTYPE_p_void 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11005123/
我不知道该怎么做... function f1() { var x = 10; function f2(fx) { var x; x = 6;
早期绑定(bind)和后期绑定(bind)有什么区别? 最佳答案 简短的回答是,早期(或静态)绑定(bind)是指编译时绑定(bind),后期(或动态)绑定(bind)是指运行时绑定(bind)(例如
如何在 SwiftUI View 上使用 Binding(get: { }, set: { }) 自定义绑定(bind)与 @Binding 属性。我已成功使用此自定义绑定(bind)与 @State
我经常发现自己遇到问题,即控件的两个(相关)值被更新,并且两者都会触发昂贵的操作,或者控件可能会暂时处于不一致的状态。 例如,考虑一个数据绑定(bind),其中两个值 (x,y) 相互减去,最终结果用
我想通过我的 ViewModel 控制我的一个窗口的高度和宽度。 这看起来很简单。 但没有。它不起作用。 它检查 ViewModel 的 Width但不是 Height . 奇怪的是,如果我切换 W
UI5中一次性绑定(bind)和单向绑定(bind)有什么区别? 是否有任何用户特定的用例我会使用它们? 我无法从文档中获得太多信息。 最佳答案 单程 它的作用:单向数据流。模型数据的变化(例如通过
(define make (lambda (x) (lambda (y) (cons x (list y))))) (let ((x 7) (p (make 4))) (cons
尽管我或多或少地了解什么是语言绑定(bind),但我很难理解它们是如何工作的。 例如,谁能解释一下如何为 WinAPI 制作 Java 绑定(bind)? 最佳答案 如果您搜索 Foreign Fun
谁能解释为什么我可以重新绑定(bind)列表但不能+? (binding [list vector] (list 1 3)) (binding [list +] (list 1 3)) (bi
我真的很喜欢 Caliburn 和命名约定绑定(bind),我很惊讶 可见性与“CanNAME”约定用于保护 Action 的方式不同。 据我所知, BooleanToVisibilityConver
我了解动态绑定(bind)的实现方式以及静态绑定(bind)和动态绑定(bind)之间的区别,但我只是无法理解动态绑定(bind)的定义。基本上它是一种运行时绑定(bind)类型。 最佳答案 基本上,
http://jsfiddle.net/3NRsd/ var foo = $("div").bind("click", function() { $("div").animate({"hei
这个问题我快疯了...我有一个用户控件,它有一个用于插入操作的 FormView 和一个用于所有其他操作的 GridView。 在这两个控件中,我都有一个 DropDownList,如下所示: '
我有一个绑定(bind)到 ListBox 的地址的 ObservableCollection。然后在 ItemTemplate 中,我使用 {Binding .} 绑定(bind)到当前地址记录。这
如果我有以下简单的 js/knockout 代码: .js( View 模型): var image = ko.observable('http://placehold.it/300x150'); 看
我正在 aurelia 上开发一个自定义属性,让用户在输入文本区域时从列表中进行选择。例如,用法将是这样的: 正如您可能注意到的,auto-complete是属性。现在,当我想显示提示时,我想在自定
我正在使用 EventEmitter2作为我的应用程序内部的消息总线。现在我需要绑定(bind)和取消绑定(bind)一些事件处理程序。因为我也希望他们bind将它们添加到给定的上下文中,我最终得到以
我有以下函数调用: $(".selector").on("click", callback.bind(this, param1, param2)); 在我的回调函数中,我想使用绑定(bind)的 th
我目前正在试验新的编译绑定(bind),并且(再次)达到了我在拼图中遗漏了一个小问题:为什么我必须调用 Bindings.Update?直到现在,我还认为实现 INotifyPropertyChang
我正在阅读一本关于编写 JavaScript 框架的书,并找到了这段代码。但是我不明白它是如何工作的,尤其是 bind.bind 的用法?有人知道吗? var bind = Function.prot
我是一名优秀的程序员,十分优秀!