这是我遇到的问题的一个非常简单的例子。 struct Foo包含包含一个int的struct Bar。如果Foo收集垃圾,那么即使仍然存在对该栏的引用,它的内部条也会被删除。防止嵌套的C++结构被父母GC'd删除
Python代码
import example
def get_bar():
foo = example.Foo()
foo.bar.x = 10
bar = foo.bar
print("before {}".format(bar.x))
return foo.bar # foo (and bar) are deleted when this returns
bar = get_bar()
print("after {}".format(bar.x))
输出
> before 10
> after 39656152
我已经消除了从C++代码的所有指针和引用,希望SWIG将使用相同的值语义,但它仍然在内部将东西转换为Foo *和Bar *。我想我的问题是,我如何说服SWIG在_wrap_Foo_bar_get中制作一个栏的副本?
实施例以下代码:
example.h文件
struct Bar {
int x;
};
struct Foo {
Bar bar;
};
example.i
%module "example"
%{
#include "example.h"
%}
%include "example.h"
的CMakeLists.txt
FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})
FIND_PACKAGE(PythonLibs)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH} .)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET(CMAKE_SWIG_FLAGS "")
SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON)
SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall")
SWIG_ADD_MODULE(example python example.i example.h)
SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES})
这里是产生SWIG方法,其抓住一个参考吧而它的值:
SWIGINTERN PyObject *_wrap_Foo_bar_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
Foo *arg1 = (Foo *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
PyObject * obj0 = 0 ;
Bar *result = 0 ;
if (!PyArg_ParseTuple(args,(char *)"O:Foo_bar_get",&obj0)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Foo, 0 | 0);
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Foo_bar_get" "', argument " "1"" of type '" "Foo *""'");
}
arg1 = reinterpret_cast< Foo * >(argp1);
result = (Bar *)& ((arg1)->bar);
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Bar, 0 | 0);
return resultobj;
fail:
return NULL;
}
听起来像是shared_ptr的情况。 –
由于您使用的是SWIG,因此我不会将此作为答案发布,但如果您使用Boost Python进行包装,它会给出诸如'copy_const_reference'和'return_internal_reference'之类的选择来适当地管理生存期(通过复制或通过将容器的生命周期延长到包含的对象的生命周期)。 –