添加swig pythoncode在Python对象上设置thisown标志
我有一个swigged C类容器,MyContainer,持有MyObject类型的对象,也是一个C类.
以下是C头代码(freemenot.h)
#ifndef freemenotH
#define freemenotH
#include <vector>
#include <string>
using std::string;
class MyObject
{
public:
MyObject(const string& lbl);
~MyObject();
string getLabel();
private:
string label;
};
class MyContainer
{
public:
MyContainer();
~MyContainer();
void addObject(MyObject* o);
MyObject* getObject(unsigned int t);
int getNrOfObjects();
private:
std::vector<MyObject*> mObjects;
};
#endif
这是源(freemenot.cpp)
#include "freemenot.h"
#include <iostream>
using namespace std;
/* MyObject source */
MyObject::MyObject(const string& lbl)
:
label(lbl)
{ cout<<"In object ctor"<<endl; }
MyObject::~MyObject() { cout<<"In object dtor"<<endl; }
string MyObject::getLabel() { return label; }
/* MyContainer source */
MyContainer::MyContainer() { cout<<"In container ctor"<<endl; }
MyContainer::~MyContainer()
{
cout<<"In container dtor"<<endl;
for(unsigned int i = 0; i < mObjects.size(); i++)
{
delete mObjects[i];
}
}
int MyContainer::getNrOfObjects() { return mObjects.size(); }
void MyContainer::addObject(MyObject* o) { mObjects.push_back(o); }
MyObject* MyContainer::getObject(unsigned int i) { return mObjects[i]; }
观察对象在向量中存储为RAW POINTERS.这个类是这样设计的,因此容器负责释放析构函数中的对象,就像在循环的析构函数中完成一样.
在C代码中,如下所示,将对象o1添加到容器c中,该对象返回到客户端代码
MyContainer* getAContainerWithSomeObjects()
{
MyContainer* c = new MyContainer();
MyObject* o1 = new MyObject();
c.add(o1);
return c;
}
返回的容器拥有其对象,并在完成后负责取消分配这些对象.在C中,在函数退出之后访问容器对象就可以了.
使用Swig将上述类公开给python将需要一个接口文件.此接口文件如下所示
%module freemenot
%{ #include "freemenot.h" %}
%include "std_string.i"
//Expose to Python
%include "freemenot.h"
为了使用CMake生成Python模块,使用了以下CMake脚本.
cmake_minimum_required(VERSION 2.8)
project(freemenot)
find_package(SWIG REQUIRED)
include(UseSWIG)
find_package(PythonInterp)
find_package(PythonLibs)
get_filename_component(PYTHON_LIB_FOLDER ${PYTHON_LIBRARIES} DIRECTORY CACHE)
message("Python lib folder: " ${PYTHON_LIB_FOLDER})
message("Python include folder: " ${PYTHON_INCLUDE_DIRS})
message("Python libraries: " ${PYTHON_LIBRARIES})
set(PyModule "freemenot")
include_directories(
${PYTHON_INCLUDE_PATH}
${CMAKE_CURRENT_SOURCE_DIR}
)
link_directories( ${PYTHON_LIB_FOLDER})
set(CMAKE_MODULE_LINKER_FLAGS ${CMAKE_CURRENT_SOURCE_DIR}/${PyModule}.def)
set_source_files_properties(${PyModule}.i PROPERTIES CPLUSPLUS ON)
set_source_files_properties(${PyModule}.i PROPERTIES SWIG_FLAGS "-threads")
SWIG_ADD_LIBRARY(${PyModule}
MODULE LANGUAGE python
SOURCES ${PyModule}.i freemenot.cpp)
SWIG_LINK_LIBRARIES (${PyModule} ${PYTHON_LIB_FOLDER}/Python37_CG.lib )
# INSTALL PYTHON BINDINGS
# Get the python site packages directory by invoking python
execute_process(COMMAND python -c "import site; print(site.getsitepackages()[0])" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
message("PYTHON_SITE_PACKAGES = ${PYTHON_SITE_PACKAGES}")
install(
TARGETS _${PyModule}
DESTINATION ${PYTHON_SITE_PACKAGES})
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PyModule}.py
DESTINATION ${PYTHON_SITE_PACKAGES}
)
使用CMake生成make文件,并使用borlands bcc32编译器进行编译,生成Python模块(freemenot)并将其安装到python3有效的sitepackages文件夹中.
然后,在Python中,可以使用以下脚本来说明问题
import freemenot as fmn
def getContainer():
c = fmn.MyContainer()
o1 = fmn.MyObject("This is a label")
o1.thisown = 0
c.addObject(o1)
return c
c = getContainer()
print (c.getNrOfObjects())
#if the thisown flag for objects in the getContainer function
#is equal to 1, the following call return an undefined object
#If the flag is equal to 0, the following call will return a valid object
a = c.getObject(0)
print (a.getLabel())
这个Python代码可能看起来很好,但不能按预期工作.问题是,当函数getContainer()返回时,如果thisown标志未设置为零,则释放对象o1的内存.使用返回的容器访问该行之后的对象将最终导致灾难.请注意,这本身没有任何问题,因为这是pythons垃圾收集的工作原理.
对于上面的用例,能够在addObject函数中设置python对象thisown标志,将呈现在Python中可用的C对象.让用户设置此标志不是一个好的解决方案.还可以使用“addObject”函数扩展python类,并修改此函数内的thisown标志,从而隐藏用户的这种内存技巧.
问题是,如何在没有扩展课程的情况下让Swig这样做?我正在寻找使用类型图,或者可能是%pythoncode,但我似乎无法找到一个好的工作示例.
上面的代码将被一个调用Python解释器的C程序使用并传递给它. C程序负责管理python函数中分配的内存,即使在PyFinalize()之后也是如此.
上面的代码可以从github https://github.com/TotteKarlsson/miniprojects下载