- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
对于一个小型Java项目,我需要与用C编写的现有代码进行交互,以便使事情变得容易(不幸的是,我不是C / C ++程序员。)我决定使用swig。
生成的包装器代码似乎可以正常工作。但是,当我调用一个应该为我提供以NULL分隔的字符串列表的函数时(如果我没有记错的话,这就是C函数应该返回的内容)包装的代码仅返回预期的第一个String值值列表。我假设Java中正确的返回数据类型将是字符串数组而不是字符串?此假设是否正确,是否可以通过在swig接口文件中指定typemap
来解决?还是我走错了路?
C头文件中的函数指出:
DllImport char *GetProjects dsproto((void));
public final static native String GetProjects();
最佳答案
解决方案1-Java
您可以通过多种方法来解决SWIG中的此问题。我从一个解决方案开始,该解决方案仅要求您编写一些Java(在SWIG接口内),然后自动应用该函数以使函数以所需的语义返回String[]
。
首先,我编写了一个小的test.h文件,使我们可以练习正在努力的类型图:
static const char *GetThings(void) {
return "Hello\0World\0This\0Is\0A\0Lot\0Of Strings\0";
}
\0
终止(最后一个隐含在C中的字符串常量中)。
%module test
%{
#include "test.h"
%}
%include <carrays.i>
%array_functions(signed char, ByteArray);
%apply SWIGTYPE* { const char *GetThings };
%pragma(java) moduleimports=%{
import java.util.ArrayList;
import java.io.ByteArrayOutputStream;
%}
%pragma(java) modulecode=%{
static private String[] pptr2array(long in, boolean owner) {
SWIGTYPE_p_signed_char raw=null;
try {
raw = new SWIGTYPE_p_signed_char(in, owner);
ArrayList<String> tmp = new ArrayList<String>();
int pos = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while (ByteArray_getitem(raw, pos) != 0) {
byte c;
while ((c = ByteArray_getitem(raw, pos++)) != 0) {
bos.write(c);
}
tmp.add(bos.toString());
bos.reset();
}
return tmp.toArray(new String[tmp.size()]);
}
finally {
if (owner && null != raw) {
delete_ByteArray(raw);
}
}
}
%}
%typemap(jstype) const char *GetThings "String[]";
%typemap(javaout) const char *GetThings {
return pptr2array($jnicall, $owner);
}
%include "test.h"
char *
,尽管我们在函数
%apply
的情况下不得不打破它,因为我们不希望这种情况发生。对数组函数使用
signed char
可以得到我们想要的:Java中的
Byte
而不是
String
的映射。
String[]
。 javaout typemap解释了我们如何根据JNI调用返回的内容(
long
,因为我们故意停止将其包装为普通的以null结尾的字符串)进行转换,而是使用了一些我们在模块内部编写的额外Java (
pptr2array
)为我们完成这项工作。
pptr2array
内部,我们实际上是在每个String中逐字节构建输出数组。我使用
ArrayList
是因为我宁愿动态增长它,也不愿对输出进行两次传递。使用
ByteArrayOutputStream
是一种逐字节构建Byte数组的好方法,它有两个主要优点:
$owner
并指示是否希望我们使用
free()
从C函数返回的内存,请使用
%newobject
。请参见
discussion of $owner
in docs。
%module test
%{
#include "test.h"
#include <assert.h>
%}
%typemap(jni) const char *GetThings "jobjectArray";
%typemap(jtype) const char *GetThings "String[]";
%typemap(jstype) const char *GetThings "String[]";
%typemap(javaout) const char *GetThings {
return $jnicall;
}
%typemap(out) const char *GetThings {
size_t count = 0;
const char *pos = $1;
while (*pos) {
while (*pos++); // SKIP
++count;
}
$result = JCALL3(NewObjectArray, jenv, count, JCALL1(FindClass, jenv, "java/lang/String"), NULL);
pos = $1;
size_t idx = 0;
while (*pos) {
jobject str = JCALL1(NewStringUTF, jenv, pos);
assert(idx<count);
JCALL3(SetObjectArrayElement, jenv, $result, idx++, str);
while (*pos++); // SKIP
}
//free($1); // Iff you need to free the C function's return value
}
%include "test.h"
native
函数将返回什么返回类型,分别是Java和C(JNI)类型。 javaout类型映射变得更简单,它所做的就是将
String[]
作为
String[]
直接传递。
String[]
的Java数组。这是通过第一步来简单地计算出有多少元素来完成的。 (在C中,没有一种整齐的方法可以做到这一点)。然后在第二遍中,我们调用
NewStringUTF
并将其存储到我们先前创建的输出数组对象中的正确位置。所有JNI调用都使用SWIG特定的
JCALLx macros,这使得它们可以在C和C ++编译器中工作。此处实际上没有必要使用它们,但是进入它并不是一个坏习惯。
const char*
字符串文字,因此我们不会释放它)。
%module test
%{
#include "test.h"
%}
%rename(GetThings) GetThings_Wrapper;
%immutable;
%inline %{
typedef struct {
const char *str;
} StrArrHandle;
StrArrHandle GetThings_Wrapper() {
const StrArrHandle ret = {GetThings()};
return ret;
}
%}
%extend StrArrHandle {
const char *next() {
const char *ret = $self->str;
if (*ret)
$self->str += strlen(ret)+1;
else
ret = NULL;
return ret;
}
}
%ignore GetThings;
%include "test.h"
GetThings()
返回类型。现在,它返回一个中间类型,该中间类型仅存在于包装器
StrArrHandle
中。
%inline
声明和定义了一个额外的函数来包装对
GetThings()
的实际调用,并使用一个额外的类型来保存它返回的指针供以后使用。
%ignore
和
%rename
仍然声称我的包装函数称为
GetThings
(即使这不是为了避免在生成的C代码内部出现名称冲突)。我本可以跳过
%ignore
而不只是在文件底部添加
%include
,但基于这样的假设:在现实世界中,您也想包装此示例的头文件中可能有更多东西是可能更有用。
%extend
将方法添加到创建的包装器类型中,该方法将返回当前字符串(如果不在末尾)并前进光标。如果您有责任释放原始函数的返回值,则还希望保留该函数的副本,并使用
%extend
添加一个“析构函数”供SWIG在对象被垃圾回收时调用。
StrArrHandle
构造
%nodefaultctor
对象。 SWIG将为
str
的
StrArrHandle
成员生成一个吸气剂。
%immutable
阻止它生成设置器,这在这里根本没有意义。您可能只是使用
%ignore
忽略了它,或者将
StrArrHandle
拆分了出来,而不是使用
%inline
,而只是不告诉SWIG该成员。
StrArrHandle ret = test.GetThings();
for (String s = ret.next(); s != null; s = ret.next()) {
System.out.println(s);
}
%typemap(jstype) StrArrHandle "String[]";
%typemap(javaout) StrArrHandle {
$javaclassname tmp = new $javaclassname($jnicall, $owner);
// You could use the moduleimports pragma here too, this is just for example
java.util.ArrayList<String> out = new java.util.ArrayList<String>();
for (String s = tmp.next(); s != null; s = tmp.next()) {
out.add(s);
}
return out.toArray(new String[out.size()]);
}
关于java - SWIG从String作为Java中的String数组获取returntype,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37253529/
我正在尝试创建一个包含 int[][] 项的数组 即 int version0Indexes[][4] = { {1,2,3,4}, {5,6,7,8} }; int version1Indexes[
我有一个整数数组: private int array[]; 如果我还有一个名为 add 的方法,那么以下有什么区别: public void add(int value) { array[va
当您尝试在 JavaScript 中将一个数组添加到另一个数组时,它会将其转换为一个字符串。通常,当以另一种语言执行此操作时,列表会合并。 JavaScript [1, 2] + [3, 4] = "
根据我正在阅读的教程,如果您想创建一个包含 5 列和 3 行的表格来表示这样的数据... 45 4 34 99 56 3 23 99 43 2 1 1 0 43 67 ...它说你可以使用下
我通常使用 python 编写脚本/程序,但最近开始使用 JavaScript 进行编程,并且在使用数组时遇到了一些问题。 在 python 中,当我创建一个数组并使用 for x in y 时,我得
我有一个这样的数组: temp = [ 'data1', ['data1_a','data1_b'], ['data2_a','data2_b','data2_c'] ]; // 我想使用 toStr
rent_property (table name) id fullName propertyName 1 A House Name1 2 B
这个问题在这里已经有了答案: 关闭13年前。 Possible Duplicate: In C arrays why is this true? a[5] == 5[a] array[index] 和
使用 Excel 2013。经过多年的寻找和适应,我的第一篇文章。 我正在尝试将当前 App 用户(即“John Smith”)与他的电子邮件地址“jsmith@work.com”进行匹配。 使用两个
当仅在一个边距上操作时,apply 似乎不会重新组装 3D 数组。考虑: arr 1),但对我来说仍然很奇怪,如果一个函数返回一个具有尺寸的对象,那么它们基本上会被忽略。 最佳答案 这是一个不太理
我有一个包含 GPS 坐标的 MySQL 数据库。这是我检索坐标的部分 PHP 代码; $sql = "SELECT lat, lon FROM gps_data"; $stmt=$db->query
我需要找到一种方法来执行这个操作,我有一个形状数组 [批量大小, 150, 1] 代表 batch_size 整数序列,每个序列有 150 个元素长,但在每个序列中都有很多添加的零,以使所有序列具有相
我必须通过 url 中的 json 获取文本。 层次结构如下: 对象>数组>对象>数组>对象。 我想用这段代码获取文本。但是我收到错误 :org.json.JSONException: No valu
enter code here- (void)viewDidLoad { NSMutableArray *imageViewArray= [[NSMutableArray alloc] init];
知道如何对二维字符串数组执行修剪操作,例如使用 Java 流 API 进行 3x3 并将其收集回相同维度的 3x3 数组? 重点是避免使用显式的 for 循环。 当前的解决方案只是简单地执行一个 fo
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我有来自 ASP.NET Web 服务的以下 XML 输出: 1710 1711 1712 1713
如果我有一个对象todo作为您状态的一部分,并且该对象包含数组列表,则列表内部有对象,在这些对象内部还有另一个数组listItems。如何更新数组 listItems 中 id 为“poi098”的对
我想将最大长度为 8 的 bool 数组打包成一个字节,通过网络发送它,然后将其解压回 bool 数组。已经在这里尝试了一些解决方案,但没有用。我正在使用单声道。 我制作了 BitArray,然后尝试
我们的数据库中有这个字段指示一周中的每一天的真/假标志,如下所示:'1111110' 我需要将此值转换为 boolean 数组。 为此,我编写了以下代码: char[] freqs = weekday
我是一名优秀的程序员,十分优秀!