2

C++クラスの(純粋な)仮想関数をオーバーライドするクラスをpythonで作成しようとしています(を使用boost.python)。問題は、C++ クラスが静的メンバー関数を介して作成されることです (すべてのコンストラクターはプライベートまたは削除されます)。Pythonが「知っている」クラス Base と BaseWrap クラスを正常に作成しました。また、Python でオーバーライドできる純粋な仮想関数を作成することもできました。ただし、私の問題は、 Base のメンバー関数が純粋仮想関数を呼び出すときです。これが発生すると、クラスは Python の実装を見つけることができず、プログラムがクラッシュします。

C++ コードは次のとおりです。

#include <iostream>
#include <boost/python.hpp>
#include <boost/static_assert.hpp>

#define CREATE(NAME) \
  static std::shared_ptr<NAME> Create() { \
    std::cout << "STATIC BASE CREATE" << std::endl; \
    return std::make_shared<NAME>();  \
  }

class Base {
protected:
  Base() { std::cout << "BASE DEFAULT CONSTRUCTOR" << std::endl; }
private:

  std::string CallSay() {
    return Say(); 
  }

  virtual std::string Say() const = 0;
};

class BaseWrap : public Base, public boost::python::wrapper<Base> {
public:
  BaseWrap() : Base() { std::cout << "BASEWRAP DEFAULT CONSTRUCTOR" << std::endl; }

  virtual std::string Say() const override
  {
    std::cout << "C++ Say" << std::endl;
    return this->get_override("say") ();
  }

  CREATE(BaseWrap)
};

BOOST_PYTHON_MODULE(Example)
{
  namespace python = boost::python;

  // Expose Base.
  python::class_<BaseWrap, std::shared_ptr<BaseWrap>, boost::noncopyable>("Base", python::no_init)
    .def("__init__", python::make_constructor(&BaseWrap::Create))
    .def("Say", python::pure_virtual(&Base::Say))
    .def("CallSay", &Base::CallSay);
}

問題をテストするための python コード:

import sys
import Example

class PythonDerived(Example.Base):
    def __init__(self):
        print "PYTHON DEFAULT CONSTRUCTOR"
        Example.Base.__init__(self)

    def Say(self):
         return "Python Say"

d = PythonDerived()
print d
print 
print d.Say()
print
print d.CallSay()

実行すると、次の出力が得られます。

PYTHON DEFAULT CONSTRUCTOR
STATIC BASE CREATE
BASE DEFAULT CONSTRUCTOR
BASEWRAP DEFAULT CONSTRUCTOR
<__main__.PythonDerived object at 0x1091caf70>

Python Say

C++ Say
Traceback (most recent call last):
  File "test.py", line 20, in <module>
    print d.CallSay()
 TypeError: 'NoneType' object is not callable

Base::CallSayメソッドが の実装を見つけているように見えBaseWrap::Sayますが、Python の実装が見つかりません。誰もがなぜ、またはどのようにこれを機能させるのか知っていますか?

ありがとう!

4

2 に答える 2