我有一个C ++库,由Java通过基于SWIG的界面调用。在Java方面,我使用默认的struct interface和carrays.i
的{{1}}构建了一个包含指向其他结构数组的指针的结构。
因为Java的垃圾收集器不知道顶级结构的成员,所以有时会释放该数组,其终结器%array_class
是其后备内存。我需要解决这个问题,最好不要在Java中复制结构,因为它相当大。
最小的例子看起来像这样(虽然它可能不会触发bug,因为它没有做太多的事情):
C ++ / SWIG:
delete[]
爪哇:
%module example
%include "carrays.i"
%array_class(object, objectArray);
struct object {
unsigned int id;
char *name;
};
struct data {
size_t nobjects;
object *objects;
};
void use_data(data*);
答案 0 :(得分:2)
这有几个可能的解决方案。最简单的是包装一个可以在没有Java“拥有”内存的情况下创建object
的函数。这可能类似于:
%inline %{
object *new_object() {
// SWIG will assume that it doesn't own this
return new object;
}
%}
您可以在创建后实际修改swigCMemOwn
boolean
。类型映射应该能够在适当的位置注入(当object
传递给setitem
时)。例如,你可以写:
%typemap(javacode) object %{
object transfer() {
swigCMemOwn = false;
return this;
}
%}
这需要在第一次见到object
课程之前,并允许你写下这样的内容:
os.setitem(i, o.transfer());
而不是os.setitem(i, o);
。
此主题的变体是使用javain
类型映射替换Java代理中的默认setitem
实现,以便它调用object
上的函数(您提供)改变所有权,例如:
%javamethodmodifiers objectArray::setitem "protected";
%rename objectArray::setitem setitemImpl;
%typemap(javacode) objectArray %{
public void setitem(int i, object o) {
o.disown();
setitemImpl(i, o);
}
%}
在%include "carrays.i"
之前的和相应的disown()
来自%typemap(javacode) object
。 (swigCMemOwn
为protected
,因此objectArray
无法直接修改此内容。
还有其他方法可能,也涉及设置所有权。我所展示的那些是我认为最简单的。
或者,通过将其分配给成员变量,另一个常见的工作是keep a reference to the Java proxy Object hanging around。在这种情况下,因为你可能有很多对象,但它们本身就必须是一个容器。