我有两个C ++类,Container和Item,看起来像:
class Item{
public:
Item(std::string* name,int id);
std::string* getName();
private:
std::string* name;
int id;
};
class Container {
public:
Container();
Item* getItem(int id);
private:
std::vector<Item*> items;
};
我想在Python中创建和使用Container,所以我编写了一个C接口来编译共享库:
extern "C" {
Container* Container_init(){return new Container();}
Item* Container_getItem(Container* container,int id){return container->getItem(id);}
std::string* Item_getName(Item* item){return item->getName();}
}
和Python包装器:
from ctypes import *
lib = cdll.LoadLibrary(myLibPath)
class Item(object):
def getName(self):
return lib.Item_getName(self.obj)
class Container(object):
def __init__(self):
self.obj = lib.Container_init()
def getItem(self,id):
return lib.Container_getItem(self.obj,id)
lib.Container_getItem.restype = Item
lib.Container_getItem.argtypes = [c_void_p,c_int]
c = Container()
print c.getItem(5).getName()
当此代码运行时,它会引发TypeError“object()在行
处不接受任何参数return lib.Container_getItem(self.obj,id)
我在documentation中读到了restype和argtype,但我显然遗漏了一些东西,我怎么能让Container.getItem
在Python中返回一个Item?
答案 0 :(得分:5)
将以下Item_getName
替换为char *
而不是string *
:
const char* Item_getName(Item* item) { return item->getName()->c_str(); }
Item
课程遗失__init__
。更改如下(这是TypeError
)的原因:
class Item(object):
def __init__(self, obj):
self.obj = obj
def getName(self):
return lib.Item_getName(self.obj)
并在Python脚本中添加以下内容(在调用getName
方法之前)以正确获取名称:
lib.Item_getName.restype = c_char_p
lib.Item_getName.argtypes = ()
然后,你会得到你想要的东西。
答案 1 :(得分:2)
您也可以使用cffi
。
这是一个cffi替代方案:
import cffi
ffi = cffi.FFI()
ffi.cdef('''
typedef struct _Item Item;
typedef struct _Container Container;
Container* Container_init();
Item* Container_getItem(Container* container,int id);
const char* Item_getName(Item* item);
''')
lib = ffi.dlopen(myLibPath)
class Item(object):
def __init__(self, obj):
self.obj = obj
def getName(self):
return lib.Item_getName(self.obj)
class Container(object):
def __init__(self):
self.obj = lib.Container_init()
def getItem(self, id):
return Item(lib.Container_getItem(self.obj, id))
c = Container()
print ffi.string(c.getItem(5).getName())