0

Python のものをプログラムに実装しようとしていて、Boost::Python を使用することにしたので、指示に従って、bjam を使用して mingw/gcc を使用し、dll と .a ファイル
を取得してコンパイルしました。これには Code::Blocks を使用するため、使用する残りの dll があるプロジェクトの作業ディレクトリに dll を配置し、実行することにしましboost::python::exec("b = 5");
た。すぐにクラッシュします。アイデア?

#include <boost/python.hpp>

float func(int a)
{
  return a*a-0.5;
}

BOOST_PYTHON_MODULE(test_module)
{
  using namespace boost::python;
  def("func", func);
}

int main()
{
  //Try one
  boost::python::exec("b = 5");
  //Crash

  //Try two
  Py_Initialize();
  boost::python::exec("b = 5");
  //Works fine

  //Try three
  Py_Initialize();
  boost::python::exec("import test_module");
  //Throws boost::python::error_already_set and crashes

  /*
    Something along the lines of
    boost::python::exec("import test_module\n"
                        "var = test_module.func( 3 )\n");
  */    
}

私のプロジェクトのビルド オプション セクションの下に、コンパイルできるように と をリンクするように追加libboost_python3-mgw48-d-1_54.dllしました。 アイデア?libpython33

4

1 に答える 1

1

Python を埋め込む場合、Python または Boost.Python へのほとんどすべての呼び出しは、インタープリターが で初期化された後に発生する必要がありますPy_Initialize()。などを使用して、初期化の前にインタープリターを呼び出そうとするとboost::python::exec()、未定義の動作が発生します。

execこれでクラッシュの原因が特定されますが、Python とモジュールを埋め込むという最終目標を達成し、埋め込みモジュールをインポートするための微妙な詳細がいくつかあります。

  • モジュールをインポートするとき、Python は最初にモジュールが組み込みモジュールかどうかをチェックします。モジュールが組み込みモジュールでない場合、Python はモジュール名に基づいてライブラリをロードしようとし、ライブラリがモジュールを初期化する関数を提供することを期待します。が組み込まれているため、組み込みモジュールを検索するときに が見つけられるtest_moduleように、その初期化を明示的に追加する必要があります。import
  • importステートメントは関数を使用します__import__execこの関数は、のグローバル内で使用できる必要があります。

これを実現する方法を示す完全な例を次に示します。

#include <boost/python.hpp>

float func(int a)
{
  return a*a-0.5;
}

BOOST_PYTHON_MODULE(test_module)
{
  using namespace boost::python;
  def("func", func);
}

// Use macros to account for changes in Python 2 and 3:
// - Python's C API for embedding requires different naming conventions for
//   module initialization functions.
// - The builtins module was renamed.
#if PY_VERSION_HEX >= 0x03000000
#  define MODULE_INIT_FN(name) BOOST_PP_CAT(PyInit_, name)
#  define PYTHON_BUILTINS "builtins"
#else
#  define MODULE_INIT_FN(name) BOOST_PP_CAT(init, name)
#  define PYTHON_BUILTINS "__builtin__"
#endif

int main()
{
  // Add the test_module module to the list of built-in modules.  This
  // allows it to be imported with 'import test_module'.
  PyImport_AppendInittab("test_module", &MODULE_INIT_FN(test_module));

  Py_Initialize();

  namespace python = boost::python;
  try
  {
    // Create an empty dictionary that will function as a namespace.
    python::dict ns;

    // The 'import' statement depends on the __import__ function.  Thus,
    // to enable 'import' to function the context of 'exec', the builtins
    // module needs to be within the namespace being used.
    ns["__builtins__"] = python::import(PYTHON_BUILTINS);

    // Execute code.  Modifications to variables will be reflected in
    // the ns.
    python::exec("b = 5", ns);

    std::cout << "b is " << python::extract<int>(ns["b"]) << std::endl;

    // Execute code using the built-in test_module.
    python::exec(
      "import test_module\n"
      "var = test_module.func(b)\n",
      ns);

    std::cout << "var is " << python::extract<float>(ns["var"]) << std::endl;
  }
  catch (python::error_already_set&)
  {
    PyErr_Print();
  }
}

実行すると、その出力は次のようになります。

b is 5
var is 24.5
于 2013-11-06T15:49:49.357 に答える