這是我遇到的問題的一個非常簡單的例子。 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'之類的選擇來適當地管理生存期(通過複製或通過將容器的生命週期延長到包含的對象的生命週期)。 –