我试图用Python和Cython扩展用C ++编写的lib的功能。我在C ++中有MyClass类,这对我的lib来说至关重要。我在Python中使用了很多它的包装类PyMyClass。所以我想使用C ++中的函数(使用PyMyClass作为参数)。我怎么能做到这一点?
我想象它是这样的:
cdef public my_func(MyClass class):
*cast MyClass to PyMyClass*
other_py_func(PyMyClass)
myclass.h
namespace classes {
class MyClass
{
public:
explicit MyClass(int x, int y);
int sum();
private:
int a;
int b;
};
}
myclass.cpp
MyClass::MyClass(int x, int y)
{
a = x;
b = y;
}
MyClass::sum()
{
return a + b
}
pymyclass.pyx
cdef extern from "myclass.h" namespace "classes":
cdef cppclass MyClass:
MyClass(int x, int y) except +
int sum()
cdef public my_func(MyClass var):
print "It is python"
cdef类PyMyClass(object): cdef MyClass * c_class
def __cinit__(self, int x, int y):
self.c_class = new MyClass(x,y)
def __dealoc__(self):
del self.c_class.sum()
def sum(self):
return self.c_class.sum()
据我所知,我可以将get_x(),get_y()和set_x(int),set_y(int)添加到MyClass,只需将MyClass中的所有字段复制到PyMyClass即可。但PyMyClass已经有一个指向MyClass的指针。是否可以将MyClass实例的地址分配给PyMyClass字段?我的意思是这样的:
cdef class PyMyClass(object):
cdef MyClass *c_class
def __cinit__(self, int x, int y):
self.c_class = MyClass(x,y)
def __cinit__(self, void * ptr):
self.c_class = (Antenna *)ptr
def __dealoc__(self):
del self.c_class.sum()
def sum(self):
return self.c_class.sum()
然后Cython函数看起来像 cdef public my_func(MyClass * class): pyclass = PyMyClass(类) other_py_func(pyclass)
答案 0 :(得分:2)
要从现有C ++指针创建Cython扩展类,请使用工厂函数。
例如:
cdef class PyMyClass:
cdef MyClass *c_class
def __cinit__(self):
# Set pointer to null on object init
self.c_class = NULL
def __dealoc__(self):
if self.c_class is not NULL:
del self.c_class
def sum(self):
return self.c_class.sum()
cdef object PyMyClass_factory(MyClass *ptr):
cdef PyMyClass py_obj = PyMyClass()
# Set extension pointer to existing C++ class ptr
py_obj.c_class = ptr
return py_obj
这使您可以通过其指针访问C ++类,而无需复制或移动任何数据。 PyMyClass_factory
可以在任何想要从现有C ++指针返回Python PyMyClass
对象的地方使用。
请注意,Python不支持函数重载(也不支持Cython),因此您不能拥有两个__cinit__
个签名,一个没有参数,另一个从两个整数创建一个新的C ++类。
如果你想通过Cython创建一个新的C ++类,那么就需要一个新的工厂函数来实现它。
看起来像是:
cdef object PyMyClass_factory_new(int x, int y):
cdef MyClass cpp_obj = new MyClass(x, y)
cdef PyMyClass py_obj = PyMyClass()
py_obj.c_class = &cpp_obj
return py_obj
此外,不需要cdef public my_func(MyClass var)
。 public
用于使Cython函数可用于C / C ++,它并不意味着它在C ++中的作用。如果您不打算在Python / Cython之外使用my_func
,则不需要public
。
如果您打算通过Python使用该功能,那么它必须是def
或cpdef
,而不是cdef
。
最后,您可能希望将外部定义定义为nogil
,并在调用C ++函数时使用with nogil
,原因很明显。例如,
cdef extern from "myclass.h" namespace "classes" nogil:
<..>
cdef class PyMyClass:
<..>
def sum(self):
cdef int ret
with nogil:
ret = self.c_class.sum()
return ret