如何包装C++;和Cython一起上课? 我有一个C++类。它由一个.ccp文件和一个.h文件组成。它可以编译(我可以编写一个在c++中成功使用它的主方法)。如何用Cython包装这个类,使它在Python中可用
我已经看过文件了,不懂。他们讨论如何生成cpp文件。当我试图遵循文档时,我已经存在的cpp被吹走了 我打算在pyx文件中放什么?我已经被告知类的定义,但有多少?仅仅是公共方法 我需要一个.pxd文件吗?我不明白什么时候需要这个文件如何包装C++;和Cython一起上课? 我有一个C++类。它由一个.ccp文件和一个.h文件组成。它可以编译(我可以编写一个在c++中成功使用它的主方法)。如何用Cython包装这个类,使它在Python中可用,c++,python,python-2.7,cython,C++,Python,Python 2.7,Cython,我已经看过文件了,不懂。他们讨论如何生成cpp文件。当我试图遵循文档时,我已经存在的cpp被吹走了 我打算在pyx文件中放什么?我已经被告知类的定义,但有多少?仅仅是公共方法 我需要一个.pxd文件吗?我不明白什么时候需要这个文件 我曾在python IRC通道中提出这些问题,但无法得到答案。 < P> Cython主要用于C开发,我将推荐C++与Python集成。他们的优秀文档应该让你很快开始。 甚至Cython通常都是用C语言,也可以生成C++代码。编译时,添加--cplus标志 现在,为类
我曾在python IRC通道中提出这些问题,但无法得到答案。
< P> Cython主要用于C开发,我将推荐C++与Python集成。他们的优秀文档应该让你很快开始。甚至Cython通常都是用C语言,也可以生成C++代码。编译时,添加
--cplus
标志
现在,为类创建包装器很简单,与包装结构没有太大区别。它主要不同于声明extern
,但这一点差别不大
假设在MyCppClass.h
中有一个类MyCppClass
cdef extern from "mycppclass.h":
cppclass MyCppClass:
int some_var
MyCppClass(int, char*)
void doStuff(void*)
char* getStuff(int)
cdef class MyClass:
# the public-modifier will make the attribute public for cython,
# not for python. Maybe you need to access the internal C++ object from
# outside of the class. If not, you better declare it as private by just
# leaving out the `private` modifier.
# ---- EDIT ------
# Sorry, this statement is wrong. The `private` modifier would make it available to Python,
# so the following line would cause an error es the Pointer to MyCppClass
# couldn't be converted to a Python object.
#>> cdef public MyCppClass* cobj
# correct is:
cdef MyCppClass* obj
def __init__(self, int some_var, char* some_string):
self.cobj = new MyCppClass(some_var, some_string)
if self.cobj == NULL:
raise MemoryError('Not enough memory.')
def __del__(self):
del self.cobj
property some_var:
def __get__(self):
return self.cobj.some_var
def __set__(self, int var):
self.cobj.some_var = var
请注意,new
关键字只有在设置了--cplus
标志时才可用,否则通过将其外部化,从
使用malloc
还请注意,调用该方法不需要取消引用指针(->
)。Cython跟踪对象的类型并应用适合的内容
.pxd文件用于将声明与实现分开,或避免名称空间冲突。假设你想把你的Python包装命名为C++类。只需将extern
声明和cimport
pxd文件放入.pyx文件中即可
cimport my_pxd
cdef my_pxd.SomeExternedType obj
请注意,您不能在.pxd文件中编写实现。因此,经过大量的戳、尝试和错误、尖叫和撕扯,我终于实现了这一点。首先,我不得不重新编写C++到C中,这对我来说,实际上只是把我所有的<代码> STD::String 变量转换成<代码> char */COD>并跟踪一些长度。 一旦完成,我就有了.h和.c文件。我想让C代码中的单个函数在Python中可用。事实证明Cython可以为您将C文件编译成扩展名,并一次链接所有库,因此从my setup.py开始,它的最终外观如下:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules=[
Extension("myext",
["myext.pyx", "../stuff.c"],
libraries=["ssl", "crypto"]
)
]
setup(
name = "myext",
cmdclass = {"build_ext": build_ext},
ext_modules = ext_modules
)
正如您所看到的,扩展名的第二个参数只是列出了所有需要编译的文件,Cython根据它们的文件扩展名来确定如何编译它们。库数组告诉Cython编译器需要链接什么(在本例中,我包装了一些加密内容,似乎无法通过现有的Python库直接模仿这些内容)
要在.pyx文件中实际使用我的C函数,需要在.pxd中编写一个小包装器。我的myext.pxd如下所示:
cdef extern from "../stuff.h":
char* myfunc(char* arg1, char* arg2, char* arg3)
然后在.pyx中使用cimport声明导入此函数,该函数可以像任何其他Python函数一样使用:
cimport myext
def my_python_func(arg1, arg2, arg3):
result = myext.myfunc(arg1, arg2, arg3)
return result
当您构建这个(至少在Mac上)时,您会得到一个.python,这样您就可以导入python并从.pyx运行函数。也许有更好、更正确的方法让这一切顺利进行,但这来自于经验,这是我第一次设法解决的问题。我对可能出错的指针非常感兴趣
更新:
在进一步使用Cython之后,我发现,和C++相比,它非常简单,一旦你知道你在做什么。使C++的string
可用只需在pyx/pyd中的libcpp.string cimport string中使用。声明C++类同样容易:
cdef extern from "MyCPPClass.h":
cdef cppclass MyCPPClass:
int foo;
string bar;
<>当然,你必须用Python格式基本上声明你的类的.h定义,但是这是一个很小的代价,为了获得你已经写的C++函数。 < P>上面的答案或多或少地回答了OP的问题。
但是现在已经过了2020年中期,我想在这里为那些希望通过可以“安装pip”(或在PyPI中)的Python包探索Python-C++绑定的人做一点贡献(以资源摘要的形式)
我想从Python/包第三方LIBS调用C++,可以看CPpyy。这是一个相对年轻的项目,但它看起来确实很有前途,并且有一个现代化的编译器作为后盾。请参阅下面的链接:
还有,总是有pybind11。。。。
Cython还支持C++(对于大多数C++语言);有关更多信息,请参阅
除了Boosi.Python、Shinboken(从pySeject项目)和SIP(从PyQT项目),我相信SWIG还可以包装C++对象。你可以在理论上用Cython来包装C++代码,但是你必须使用被损坏的名字,并且手工做很多东西。我自己不会推荐它。因为我非常重视Boost和它的许多库的质量,当我给出一个选项列表时通常是我的首选。至于你提出的选择:PySide是相对较新的,就我而言,未经证实。SIP是一个GPL许可证,这可能会阻止一些人。我对SWIG有过一些不愉快的经历,所以我自己不能推荐它。和往常一样,YMMV,但在我看来,Boost几乎不会出错。@spatz很抱歉,我不能同意Boost.Python的优秀文档,甚至是Boost的一般文档。我发现他们的文档在过去完全是误导或缺失的。几个月前,我正在使用他们的网络/套接字库,这是一个大量的尝试和错误。@Endophage,我并没有说Boost的所有文档都很好,我只是指Boost.Python文档