如何在SWIG中从C指针生成Java数组

3

以下是这段C代码:

typedef struct _B {
 /* something */
} B;

typedef struct _A {
    int numBs; /* The count of Bs in the array bellow */
    B *b;
} A;

我想在Java中将A.b作为数组访问
A a = new A();
B[] b = a.getB();

你知道如何使用SWIG实现这个吗?我尝试使用carrays.i,但没有成功。需要考虑到B *b不一定是一个数组,只在特定情况下是。


使用原始地址创建一个NIO直接字节缓冲区,然后使用NIO缓冲区方法将内存作为数组访问。 - technomage
你好,谢谢。你能给一个例子来实现这个(SWIG接口文件)吗?我能得到的最好结果是B b = a.getB()而不是B[] b = a.getB() - kalamar
1个回答

4
我们可以使用SWIG来实现这一点。棘手的部分是,正如你所发现的那样,SWIG倾向于认为B*是指向Object的指针,而不是某个数组的开头。
由于数组包含许多非基本实例,每个实例都需要创建一个Java对象,该对象是对C数组中相应B实例的代理。有两个地方可以生成这些代理。要么编写一些C代码创建每个Object并将其放入jobjectArray中,要么编写一些Java代码利用SWIG可以轻松生成任何特定成员的特定代理的事实。我认为后者的解决方案更简单、更清晰,因此我已经提供了一个使用这种方法的示例:
%module test

%ignore A_::b; // We will wrap this another way
%typemap(javacode) A %{
  public B[] getB() {
    B[] ret = new B[getNumBs()];
    for (int i = 0; i < ret.length; ++i) {
      ret[i] = getB(i);
    }
    return ret;
  }
%}

// Or %include etc.
%inline %{
typedef struct B_ {
 /* something */
} B;

typedef struct A_ {
    int numBs; /* The count of Bs in the array bellow */
    B *b;
} A;
%}

%javamethodmodifiers A_::getB(size_t pos) "private";
%extend A_ {
  // This defaults to non-owning, which is exactly what we want
  B *getB(size_t pos) {
    assert(pos < $self->numBs); // TODO: real error handling
    return $self->b+pos;
  }
}
%extend为Java提供了一个额外的方法,用于获取C数组中的任何B。由于这是一个实现细节,我将其设为私有。
我们还告诉SWIG不要包装B * b指针,而是手动提供自己的包装。这是通过javacode类型映射提供的。在该类型映射中,我们通过调用帮助程序每个数组项一次来构建我们的Java数组。
有了这些,现在你只需要执行以下操作即可:
A a = new A();
B[] b = a.getB();

重要的是,因为我们只忽略了A的特定成员,它不会干扰对B *b的其他使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接