简体   繁体   English

C++ 和 Boost.Python - 如何将变量暴露给 python 并在循环中更新它?

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

Introduction介绍

I have a python code called from c++, using boost.python package.我有一个从 C++ 调用的 python 代码,使用 boost.python 包。 I can pass some variables, when calling MyFunc from .py like this:当从 .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();
}

However I need another variable, lets call it var4 , to be updated, basing on C++ GUI, on every loop of my python code.但是我需要另一个变量,我们称之为var4 ,基于 C++ GUI,在我的 python 代码的每个循环中进行更新。 If I understand correctly MyFunc(var1, var2, var3) pass the value only once, at the beginning, so even if i change the value of var1 after executing it, it will not affect python code.如果我理解正确MyFunc(var1, var2, var3)在开始时只传递一次值,所以即使我在执行后更改var1的值,它也不会影响 python 代码。

The problem问题

Is there any way, to expose c++ variable, so it will be updated "live" in python code?有什么办法可以公开 c++ 变量,以便在 python 代码中“实时”更新它? If all would be in one language it will be trivial (with global variables for example), but on the edge of two environment it becomes tricky.如果全部使用一种语言,这将是微不足道的(例如使用全局变量),但在两种环境的边缘它变得棘手。

Edit:编辑:

I was trying to expose variable gui_cancel like this:我试图像这样公开变量gui_cancel

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

But accessing it from python this way:但是通过这种方式从 python 访问它:

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

Give me only the property of the object:只给我对象的属性:

<property object at 0x0000012D9AA90BD8>

I don't know how you would expose a variable directly, but you can always expose a C function, and have that C function return the current value of the variable to the Python script when the Python script calls it.我不知道如何直接公开变量,但您始终可以公开 C 函数,并让该 C 函数在 Python 脚本调用它时将变量的当前值返回给 Python 脚本。

Below is an example C program that demonstrates the technique.下面是一个演示该技术的示例 C 程序。 Note that main() runs a simple Python script that calls the included C function GetRandomNumber() .请注意, main()运行一个简单的 Python 脚本,该脚本调用包含的 C 函数GetRandomNumber() GetRandomNumber() chooses a random number and prints its value to stdout, and then returns it to the Python script. GetRandomNumber()选择一个随机数并将其值打印到 stdout,然后将其返回给 Python 脚本。 The Python script then prints out the value as well, so you can verify that the Python code printed the same value that the C code chose.然后 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;
}

When I run the above program, I see this output:当我运行上面的程序时,我看到了这个输出:

$ ./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