我们可以用 SWIG 做到这一点。棘手的部分是,正如您发现的那样,SWIG 倾向于假设它B*
是指向 an 的指针Object
,而不是某个数组的开头。
由于数组包含许多非原始实例,每个实例都需要创建一个 Java 对象,该对象是B
C 数组中相应实例的代理。有两个地方可以导致它们生成。您可以编写一些 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;
}
}
在%extend
Java 中提供了一种额外的方法,可以获取B
C 数组中的任何B
s。由于这是一个实现细节,我将其设为私有。
我们还告诉 SWIG 不要包装B *b
指针 - 我们将手动为其提供我们自己的包装。这是通过类型javacode
映射提供的。在该类型映射中,我们通过对数组中的每个项目调用一次帮助程序来构建我们的 Java 数组。
有了这些,您现在就足够了:
A a = new A();
B[] b = a.getB();
至关重要的是,因为我们只忽略了它的特定成员,A
不会干扰B *b
.