3

给出的是这个 C 代码:

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

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

我想在 Java 中将 Ab 作为数组访问

A a = new A();
B[] b = a.getB();

你有一个想法如何用 SWIG 做到这一点吗?我玩了carrays.i,但没有成功。考虑到B *b它并不总是必须是一个数组,只有在这个特定的结构中。

4

1 回答 1

4

我们可以用 SWIG 做到这一点。棘手的部分是,正如您发现的那样,SWIG 倾向于假设它B*是指向 an 的指针Object,而不是某个数组的开头。

由于数组包含许多非原始实例,每个实例都需要创建一个 Java 对象,该对象是BC 数组中相应实例的代理。有两个地方可以导致它们生成。您可以编写一些 C 来创建每个 CObject并将其粘贴在 a 中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;
  }
}

%extendJava 中提供了一种额外的方法,可以获取BC 数组中的任何Bs。由于这是一个实现细节,我将其设为私有。

我们还告诉 SWIG 不要包装B *b指针 - 我们将手动为其提供我们自己的包装。这是通过类型javacode映射提供的。在该类型映射中,我们通过对数组中的每个项目调用一次帮助程序来构建我们的 Java 数组。

有了这些,您现在就足够了:

A a = new A();
B[] b = a.getB();

至关重要的是,因为我们只忽略了它的特定成员,A不会干扰B *b.

于 2013-08-24T20:32:06.203 回答