簡體   English   中英

C++ 和 Boost.Python - 如何將變量暴露給 python 並在循環中更新它?

[英]C++ and Boost.Python - how to expose variable to python and update it in loop?

介紹

我有一個從 C++ 調用的 python 代碼,使用 boost.python 包。 當從 .py 調用MyFunc時,我可以傳遞一些變量,如下所示:

Py_SetPythonHome(pySearchPath);
try
{
Py_Initialize();
numpy::initialize();
object module = import("__main__");
object name_space = module.attr("__dict__");
exec(python_full, name_space, name_space);
object MyFunc = name_space["MyFunc"];

object result = MyFunc(var1, var2, var3)); //HERE

//Python results storage
numpy::ndarray ret = extract<numpy::ndarray>(result);
int input_size = ret.shape(0);
std::vector<std::vector<double>> v(input_size, std::vector<double>(50));
}
catch (error_already_set)
{
    PyErr_Print();
}

但是我需要另一個變量,我們稱之為var4 ,基於 C++ GUI,在我的 python 代碼的每個循環中進行更新。 如果我理解正確MyFunc(var1, var2, var3)在開始時只傳遞一次值,所以即使我在執行后更改var1的值,它也不會影響 python 代碼。

問題

有什么辦法可以公開 c++ 變量,以便在 python 代碼中“實時”更新它? 如果全部使用一種語言,這將是微不足道的(例如使用全局變量),但在兩種環境的邊緣它變得棘手。

編輯:

我試圖像這樣公開變量gui_cancel

BOOST_PYTHON_MODULE(cbtest)
{
    class_<callback_handler, boost::noncopyable>("callback_handler", no_init)
        .def_readwrite("gui_cancel", &callback_handler::gui_cancel);
        ;
};

但是通過這種方式從 python 訪問它:

import cbtest
holder = cbtest.callback_handler
print(holder.gui_cancel)

只給我對象的屬性:

<property object at 0x0000012D9AA90BD8>

我不知道如何直接公開變量,但您始終可以公開 C 函數,並讓該 C 函數在 Python 腳本調用它時將變量的當前值返回給 Python 腳本。

下面是一個演示該技術的示例 C 程序。 請注意, main()運行一個簡單的 Python 腳本,該腳本調用包含的 C 函數GetRandomNumber() GetRandomNumber()選擇一個隨機數並將其值打印到 stdout,然后將其返回給 Python 腳本。 然后 Python 腳本也會打印出該值,因此您可以驗證 Python 代碼打印的值是否與 C 代碼選擇的值相同。

#include <Python.h>
#include <stdio.h>

static PyObject * GetRandomNumber(PyObject * pyObj, PyObject * args, PyObject * keywords)
{
   const int randomNumber = rand();
   printf("C Function GetRandomNumber():  I choose:  %i\n", randomNumber);
   return PyLong_FromLong(randomNumber);
}

static PyMethodDef DemoEditorMethods[] = {
   {"GetRandomNumber", (PyCFunction)GetRandomNumber, METH_KEYWORDS | METH_VARARGS, "Returns a random integer."},
   {NULL, NULL, 0, NULL}  // list terminator
};

PyDoc_STRVAR(demo_doc, "This module is just here to demonstrate calling a C function from Python and having it return a value.");

static struct PyModuleDef DemoModuleDefinition = {
   PyModuleDef_HEAD_INIT,
   "embedded_demo",
   demo_doc,
   -1,
   DemoEditorMethods,
   NULL,
   NULL,
   NULL,
   NULL
};

int main(int argc, char *argv[])
{
    Py_Initialize();

    // Note:  if this line is causing you link errors under Windows,,
    // try rebuilding pythoncore.lib in "Release Mode" instead of
    // "Debug mode".
    PyObject * csMod = PyModule_Create(&DemoModuleDefinition);
    if (csMod)
    {
       PyObject *modules = PyImport_GetModuleDict();
       if (modules)
       {
          PyObject * nameObj = PyUnicode_FromString("embedded_demo");
          if ((nameObj == NULL)||(PyObject_SetItem(modules, nameObj, csMod) != 0)) printf("PyObject_SetItem() failed!?\n");
       }
       else printf("PyImport_GetModuleDict() returned NULL!\n");
    }
    else printf("Unabled to create embedded_demo Python module!\n");

    if (PyImport_ImportModule("embedded_demo") == NULL) printf("Unable to import embedded_demo Python module!\n");

    PyRun_SimpleString(
        "import sys;"
        "import embedded_demo;"
        "v = embedded_demo.GetRandomNumber();"
        "print('Python Script:  The random value I got from the C GetRandomNumber() function is: %i' % v);"
    );
    Py_Finalize();
    return 0;
}

當我運行上面的程序時,我看到了這個輸出:

$ ./test_c_function_call
C Function GetRandomNumber():  I choose:  16807
Python Script:  The random value I got from the C GetRandomNumber() function is: 16807

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM