2013-06-02 2 views
7

Я подозреваю, что есть простой ответ на этот вопрос, но мне нужна помощь в начале работы с Cython. У меня есть существующая база кода C++, которую я хочу открыть Python через Cython. Для каждого класса, который я хочу открыть, я создаю Cython cppclass _ClassName и класс оболочки Python ClassName.Как вернуть новые объекты C++ в Cython?

minmal пример:

Object.h 
CythonMinimal.pyx 
setup.py 

содержание Object.h:

class Object { 

public: 

    Object clone() { 
     Object o; 
     return o; 
    } 

}; 

содержание CythonMinimal.pyx:

cdef extern from "Object.h": 
    cdef cppclass _Object "Object": 
     _Object() except + 
     _Object clone() 


cdef class Object: 

    cdef _Object *thisptr 

    def __cinit__(self): 
     self.thisptr = new _Object() 

    def __dealloc__(self): 
     del self.thisptr 

    def clone(self): 
     return self.thisptr.clone() 

содержание setup.py

from distutils.core import setup 
from distutils.extension import Extension 
from Cython.Build import cythonize 
from Cython.Distutils import build_ext 

import os 

os.environ["CC"] = "g++-4.7" 
os.environ["CXX"] = "g++-4.7" 


modules = [Extension("CythonMinimal", 
        ["CythonMinimal.pyx"], 
        language = "c++", 
        extra_compile_args=["-std=c++11"], 
        extra_link_args=["-std=c++11"])] 

for e in modules: 
    e.cython_directives = {"embedsignature" : True} 

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

Это ошибка я получаю при компиляции:

cls ~/workspace/CythonMinimal $ python3 setup.py build 
running build 
running build_ext 
cythoning CythonMinimal.pyx to CythonMinimal.cpp 

Error compiling Cython file: 
------------------------------------------------------------ 
... 

    def __dealloc__(self): 
     del self.thisptr 

    def clone(self): 
     return self.thisptr.clone() 
         ^
------------------------------------------------------------ 

    CythonMinimal.pyx:18:27: Cannot convert '_Object' to Python object 
    building 'CythonMinimal' extension 
    creating build 
    creating build/temp.macosx-10.8-x86_64-3.3 
    g++-4.7 -Wno-unused-result -fno-common -dynamic -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -I/usr/local/include -I/usr/local/opt/sqlite/include -I/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/include/python3.3m -c CythonMinimal.cpp -o build/temp.macosx-10.8-x86_64-3.3/CythonMinimal.o -std=c++11 
    cc1plus: warning: command line option '-Wstrict-prototypes' is valid for C/ObjC but not for C++ [enabled by default] 
    CythonMinimal.cpp:1:2: error: #error Do not use this file, it is the result of a failed Cython compilation. 
    error: command 'g++-4.7' failed with exit status 1 

Я предполагаю, что _Object.clone должна возвращать _Object (тип cppclass), но Objet.clone должен возвращать Object (тип Python). Но как?

+0

Не могли бы вы y уменьшите это до строго минимального примера (например, не более одного .h заголовочного файла), и размещать здесь ВСЕ файлы (код C++, заголовок .h, setup.py, оболочка cython, приложение python)? Поскольку не существует всеобъемлющей документации по связыванию Cython/C++, для многих из нас было бы полезно сотрудничать здесь (или на [email protected]?), Чтобы получить один минимальный пример. –

+0

Я попытаюсь построить минимальный пример. Но неправильно ли мне думать, что это довольно общий вопрос начинающего, и решение должно быть очевидно для кого-то с опытом Cython + C++? – clstaudt

+0

Существует не так много опытных разработчиков Cython/C++, и маловероятно, что они станут более многочисленными, если документация не будет улучшена. Для меня лично, изучение Cython/C++ является высоким в моей повестке дня; но после первой попытки, которая закончилась нерешенными проблемами, я отложил дальнейшие усилия. Поэтому я хотел бы попробовать заново с вашим примером ... –

ответ

5

Вы возвращаете C++ объект в функции питона, которым разрешено возвращать только объекты Python:

def clone(self): 
    return self.thisptr.clone() 

Сделать это так:

cdef _Object clone(self) except *: 
    return self.thisptr.clone() 

Но это зависит от того, что вы пытаетесь чтобы сделать это, вы, вероятно, захотите вернуть объект, а не _Object, поэтому я бы изменил его таким образом:

cdef class Object: 
    cdef _Object thisobj 
    cdef _Object *thisptr  

    def __cinit__(self, Object obj=None): 
     if obj: 
      self.thisobj = obj.thisobj.clone() 
     self.thisptr = &self.thisobj 

    def __dealloc__(self): 
     pass 

    def clone(self): 
     return Object(self) 
+0

Правильно, я хочу вернуть 'Object', а не' _Object' – clstaudt

+0

Я думал, что это может работать как общее решение, а не только в специальный случай этого примера, где существует метод clone: ​​'def __cinit __ (self, _Object obj = None): ...' But '__cinit__' не принимает' _Object', потому что он не может преобразовать его в объект Python. – clstaudt

+2

@cls Вы не можете передавать объекты C++ в конструкторы, это не разрешено, но вы можете установить свойство после создания объекта. 'obj = Object(); obj.thisptr = myCppObj; '.Вы можете создать для этого функции-оболочки: 'cdef CreateObject (_Object _obj): obj = Object(); obj.thisptr = _obj; return obj; '. –

Смежные вопросы