【问题标题】:C++ and Boost.Python - how to expose variable to python and update it in loop?C++ 和 Boost.Python - 如何向 python 公开变量并在循环中更新它?
【发布时间】:2020-05-05 17:33:28
【问题描述】:

简介

我有一个使用 boost.python 包从 c++ 调用的 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)

只给我对象的属性:

&lt;property object at 0x0000012D9AA90BD8&gt;

【问题讨论】:

  • 按照你的写法,cbtest.callback_handler 是一个类,gui_cancel 是它的数据成员。您需要先实例化此类,然后才能访问其非静态成员。既然你做到了no_init,你就需要在 C++ 端这样做。 | gui_cancel的数据类型是什么?
  • TBH,而不是公开一个变量,我会采用 Jeremy Friesner 建议的方法(但没有所有低级的东西)。只需公开两个简单的包装函数,它们将获取和设置值。

标签: python c++ qt boost boost-python


【解决方案1】:

我不知道如何直接公开一个变量,但你总是可以公开一个 C 函数,并让该 C 函数在 Python 脚本调用它时将变量的当前值返回给 Python 脚本。

下面是一个演示该技术的示例 C 程序。请注意,main() 运行一个简单的 Python 脚本,该脚本调用包含的 C 函数 GetRandomNumber()GetRandomNumber() 选择一个随机数并将其值打印到标准输出,然后将其返回给 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

【讨论】:

  • 谢谢,我可以通过在BOOST_PYTHON_MODULEBOOST_PYTHON_MODULE中公开包含该函数的类,在 C++ 中重现它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 1970-01-01
  • 1970-01-01
  • 2016-06-27
  • 2019-03-05
  • 1970-01-01
  • 2021-06-29
相关资源
最近更新 更多