6

埋め込まれたPython3.xをC/C++で拡張するプログラムの標準的な例を次に示します。

#include <Python.h>
//// Definition of 'emb' Python module ////////////////////
static PyObject* emb_foo(PyObject *self, PyObject *args)
{
    char const* n = "I am foo";
    return Py_BuildValue("s", n);
}
static PyMethodDef EmbMethods[] = {
    {"foo", emb_foo, METH_VARARGS, "Returns foo"},
    {NULL, NULL, 0, NULL}
};
static PyModuleDef EmbModule = {
    PyModuleDef_HEAD_INIT, "emb", NULL, -1, EmbMethods,
    NULL, NULL, NULL, NULL
};
static PyObject* PyInit_emb(void)
{
    return PyModule_Create(&EmbModule);
}
//// Embedded Python with 'emb' loaded ////////////////////
int main()
{
    PyImport_AppendInittab("emb", &PyInit_emb);
    Py_Initialize();

    PyRun_SimpleString("import emb\n");       // (1)
    //PyImport_ImportModule("emb");           // (2)

    PyRun_SimpleString("print(emb.foo())\n"); // (3)

    Py_Finalize();
    return 0;
}

emb組み込みインタプリタのビルトインにモジュールを追加します。また、自動的にインポートしたいので、ユーザーはimport emb、埋め込まれたインタープリターに提供されたスクリプトでステートメントを発行する必要がありません。(1)行と(2)行の2つのインポート方法を試しています。

1)は機能し、モジュールは(3)emb行の簡単なテストで明示的にインポートしなくても見つけることができます。ただし、行(1)をコメントアウトし、行(2)のコメントを解除してPython3呼び出しのCAPIでインポートすると、行(3)でエラーが発生します。

Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'emb' is not defined

ここで、2つのインポート方法の違いを理解したいと思います。モジュールを異なる名前空間/スコープにインポートしますか?

Python 3のドキュメントは、私をこの道に導きました。

  1. PyImport_ImportModuleは、組み込みのPython関数を参照することで最もよく説明されます__import__()
  2. __import__()関数はimportステートメントによって呼び出されます。

おそらく、PyImport_ImportModule1対1で同等であると想定して間違いを犯し、正しい(正確には?)グローバルとローカルでPyImport_ImportModuleExを使用する必要があるため、「emb」は埋め込みインタープリターのグローバル名前空間に配置されます。

4

1 に答える 1

9

__import__モジュールを名前空間にまったく配置しませんが、代わりにそれを返します。 importを呼び出し__import__、さらに結果を変数に格納します。ドキュメントによると、これは次のimport spamようなことをします。

spam = __import__('spam', globals(), locals(), [], 0)

embC APIで同じ効果を得るには、グローバルに割り当てる必要があります。つまり、モジュールにemb属性を設定し__main__ます。

PyObject* emb_module = PyImport_ImportModule("emb");
PyObject* main_module = PyImport_AddModule("__main__");
PyObject_SetAttrString(main_module, "emb", emb_module);
Py_XDECREF(emb_module);
/* (main_module is a borrowed reference) */
于 2011-11-03T17:37:14.213 に答える