如何包装C++;和Cython一起上课? 我有一个C++类。它由一个.ccp文件和一个.h文件组成。它可以编译(我可以编写一个在c++中成功使用它的主方法)。如何用Cython包装这个类,使它在Python中可用

如何包装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标志 现在,为类

我已经看过文件了,不懂。他们讨论如何生成cpp文件。当我试图遵循文档时,我已经存在的cpp被吹走了

我打算在pyx文件中放什么?我已经被告知类的定义,但有多少?仅仅是公共方法

我需要一个.pxd文件吗?我不明白什么时候需要这个文件


我曾在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文档