Python Cython使用structs的字符串成员函数表现异常

Python Cython使用structs的字符串成员函数表现异常,python,c++,struct,cython,Python,C++,Struct,Cython,我有一个结构,看起来像这样: foo.h: struct A { string a; string b; }; 它在.pyx文件中具有匹配的定义,以及python包装器: lib_foo.pyx: cdef extern from "foo.h": cdef struct A: string a string b cdef class PyA: cdef A* thisptr def __cinit__(self):

我有一个结构,看起来像这样:

foo.h:

struct A { 
    string a;
    string b;
};
它在.pyx文件中具有匹配的定义,以及python包装器:

lib_foo.pyx:

cdef extern from "foo.h":
    cdef struct A:
        string a
        string b

cdef class PyA:
    cdef A* thisptr
    def __cinit__(self):
        self.thisptr = <A*>malloc(sizeof(A))
    cdef A* getThis(self):
        return self.thisptr
    def bar(self):
        self.thisptr.a = "Hello" # works fine!
    def bar2(self):
        return self.thisptr.a # this too!

def bar(PyA f):
    f.getThis().a = "Hello"

def bar2(PyA a):
    return f.getThis().a
在重复运行过程中,有时会成功打印“Hello”,有时会打印segfault。更奇怪的是,bar和bar2这两个函数作为PyA类的成员函数似乎工作得很好。我做了很多cython包装,只使用了这样一个getThis()函数来提供类和结构的指针,直到现在都没有问题。是否是字符串导致了问题

编辑:setup.py

from distutils.core import setup
import distutils.util as du
from distutils.extension import Extension
from Cython.Distutils import build_ext
import os

os.environ["CC"] = "/app/gcc/4.8.2/bin/g++"
os.environ["CXX"] = "/app/gcc/4.8.2/bin/g++"
os.environ["CPP"] = "/app/gcc/4.8.2/bin/g++"
os.environ["CMAKE_CXX_COMPILER"] = "/app/gcc/4.8.2/bin/g++"

ext_modules = [
    Extension(
        name = "libfoo",
        sources = ["lib_foo.pyx"],
        include_dirs = ["/usr/local/include", "/usr/include"],
        library_dirs = ["/usr/local/lib", "/usr/lib"],
        language = "c++",
    )]

setup(
    name = "libfoo",
    cmdclass = {"build_ext" : build_ext},
    ext_modules = ext_modules
    )

首先,您必须告诉Cython,StultA/Cuth>具有C++类语义(CDEF CppCys),而不是C结构语义(CDEF Stult),因为它具有嵌入字符串的非平凡构造函数。

from libcpp.string cimport string

cdef extern from "foo.h":
    cdef cppclass A:
        string a
        string b

然后分配给运算符<代码>新< /C> >,而不是MALOC,就像您在C++中所做的一样。

def __cinit__(self):
    self.thisptr = new A()
绕过构造函数并使用未初始化实例是导致崩溃的原因

在释放Python包装器时,不要忘记删除此对象:

def __dealloc__(self):
    del self.thisptr
另外,提供明确的方法以确定地释放C级资源(独立于Python GC)也是一个好主意:


我们能有完整且可运行的示例吗?您当前的文件无法编译。好的,我已将setup.py包含在编辑中。但是它应该编译得很好,你会得到什么样的编译错误?很遗憾我不能改变C++源代码。我已经使用了这种包装类而不是结构的方法。我希望结构类似,它与C++源无关。您需要通知Cython,<代码> Stutt A /Cuff>使用C++代码,使用<代码> CDEF CppCype < /C> >代替<代码> CDEF结构> /COD>。用于在C++中声明的实际关键字是无关的。哇,是这样做的。结构和类显然是不同的东西,cython如何将它们解释为相同的东西?我知道类与结构类似,但在面向对象的意义上。无论如何,享受你的赏金吧:)
def __dealloc__(self):
    del self.thisptr
def dispose(self):  # or "close" or whatever
    del self.thisptr
    self.thisptr = NULL