2017-10-31 14 views
0

defを使って定義されたCythonメソッドのPythonオブジェクト引数をC++型に変換するにはどうすればよいですか?私は、CythonのドキュメントのUsing C++ in Cythonセクションに記述されているように、C++ライブラリ用のCythonラッパークラスを提供しようとしています。PythonオブジェクトをCythonのC++型に変換する方法

ここに私の問題を示す例があります。

ファイルfoo.h

namespace ns { 
    class Foo: 
    public: 
     Foo(); 
     dosomething(std::shared_ptr<Bar>); 
} 

ファイルbar.h

namespace ns { 
    class Bar: 
    public: 
     Bar(); 
} 

ファイルfoo.pyx

from libcpp.memory cimport shared_ptr 

cdef extern from 'bar.h' namespace 'ns': 

    cdef cppclass Bar: 
     Bar() except + 


cdef extern from 'foo.h' namespace 'ns': 

    cdef cppclass Foo: 
     Foo() except + 
     void dosomething(shared_ptr[Bar]) 


cdef class PyBar: 

    cdef Bar* thisptr 

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

    def __dealloc__(self): 
     del self.thisptr 


cdef class PyFoo: 

    cdef Foo* thisptr 

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

    def __dealloc__(self): 
     del self.thisptr 

    def dosomething(self, bar): 
     self.thisptr.dosomething(bar) 

ファイルsetup.py

from setuptools import Extension 
from setuptools import setup 

from Cython.Build import cythonize 

extensions = [ 
    Extension(
     'foo', 
     sources=[ 
      'foo.pyx', 
      'foo.cpp', 
      'bar.cpp', 
     ], 
     language='c++', 
     include_dirs=['.'], 
     extra_compile_args=['-std=c++11'], 
    ), 
] 

setup(
    ext_modules=cythonize(extensions), 
) 

私はこのコンパイルしようとしたときに発生するエラー:

$ python setup.py build_ext 
Compiling foo.pyx because it changed. 
[1/1] Cythonizing foo.pyx 

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

def __dealloc__(self): 
    del self.thisptr 

def dosomething(self, bar): 
    self.thisptr.dosomething(bar) 
       ^
------------------------------------------------------------ 

foo.pyx:38:33: Cannot convert Python object to 'shared_ptr[Bar]' 

答えて

0

を、私は私が言っているかと思いますが、foo and barは本当に愚かな例であり、C++コードを完了するために、欲しいものは考えています、論理と実装なし。しかし、私もあなたのことに基づいてそのような愚かな例を作って、それを働かせました。トリッキーでバギーで、少しでも助けてくれることを願っています。

%%file foo.h 
#include <memory> 

namespace ns { 

    class Bar{ 
    public: 
     Bar(){}; 
    }; 

    class Foo{ 
    public: 
     Foo(): bar_addr(0) {} 
     void dosomething(std::shared_ptr<Bar> sp){bar_addr = (size_t)sp.get();} 
     size_t get_bar_addr(){return bar_addr;} 
    private: 
     size_t bar_addr; 
    }; 
} 

Cythonの部品::

%%cython -f -+ -a 
# distutils: include_dirs = . 

from libcpp.memory cimport shared_ptr 


cdef extern from 'foo.h' namespace 'ns': 

    cdef cppclass Foo: 
     Foo() except + 
     void dosomething(shared_ptr[Bar]) 
     size_t get_bar_addr() 

    cdef cppclass Bar: 
     Bar() except + 


cdef class PyBar: 

    cdef Bar* thisptr 

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

    def __dealloc__(self): 
     del self.thisptr 

    def addr(self): 
     return <size_t><void*>self.thisptr 


cdef class PyFoo: 

    cdef Foo* thisptr 
    # There is a bug here, see the comments 
    cdef PyBar owned_bar # keep this bar to prevent the underlying pointer losing. 
    cdef shared_ptr[Bar] owned_bar_sp # keep this bar shared_ptr to prevent the underlying pointer from deleting. 

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

    def __dealloc__(self): 
     del self.thisptr 

    def dosomething(self, PyBar bar): 
     self.owned_bar = bar 
     print("Address passed in: ", self.owned_bar.addr()) 
     self.owned_bar_sp = shared_ptr[Bar](<Bar*><size_t>self.owned_bar.addr()) 
     self.thisptr.dosomething(self.owned_bar_sp) 
     print("Address got  : ", self.thisptr.get_bar_addr()) 

テスト:

は私がコンパイル簡素化するためにjupyterノートブックを使用して、あなたの質問「どのようにCにPythonオブジェクトを変換するために約

bar = PyBar() 
foo = PyFoo() 

foo.dosomething(bar) 

を++ Cython "と入力すると、私は答えが" Can "か" Can not "か" Possibl " e "であり、コンテクストに依存する。この特定の例では、「できません」。あなたはCythonでいくつかの構造や変換を行う必要があります。これはPythonとC/C++の間の橋渡しの役割を果たします。

+1

私はこのようにしてはいけないと思います:1)owned_bar事業は不要です。それはdosomethingで使用されている間削除されません。 2)dosomethingを呼び出した後、PyBar.thisptrが2倍になりました。一度__dealoc__によってshared_ptrを一回実行しました。 – ead

+1

cpp-interfaceのshared_ptrに問題があります。多分Bar.thisptrはshared_ptr型でなければなりません。[Bar] – ead

+0

@head良い点!私は本能的にバギーだと感じています。編集してください。 – oz1

関連する問題