C ++和Boost.Python-如何将变量公开给python并循环更新? [英] C++ and Boost.Python - how to expose variable to python and update it in loop?

查看:86
本文介绍了C ++和Boost.Python-如何将变量公开给python并循环更新?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简介

我有一个使用boost.python包从c ++调用的python代码.当从.py调用MyFunc时,我可以传递一些变量,如下所示:

I have a python code called from c++, using boost.python package. I can pass some variables, when calling MyFunc from .py like this:

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,以便基于python代码的每个循环基于C ++ GUI进行更新.如果我正确理解MyFunc(var1, var2, var3)在开始时只传递一次值,那么即使我在执行后更改var1的值,也不会影响python代码.

However I need another variable, lets call it var4, to be updated, basing on C++ GUI, on every loop of my python code. 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.

问题

有没有办法公开c ++变量,因此它将在python代码中实时"更新?如果全部使用一种语言,将是微不足道的(例如,使用全局变量),但是在两种环境的边缘,它将变得很棘手.

Is there any way, to expose c++ variable, so it will be updated "live" in python code? 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.

我试图像这样公开变量gui_cancel:

I was trying to expose variable gui_cancel like this:

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

但是可以通过以下方式从python访问它:

But accessing it from python this way:

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

仅给我对象的属性:

<property object at 0x0000012D9AA90BD8>

推荐答案

我不知道如何直接公开变量,但是您始终可以公开C函数,并让C函数返回当前的值. Python脚本调用它时,将其变量设置为Python脚本.

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程序.请注意,main()运行一个简单的Python脚本,该脚本调用包含的C函数GetRandomNumber(). GetRandomNumber()选择一个随机数并将其值打印到stdout,然后将其返回到Python脚本.然后,Python脚本也会打印出该值,因此您可以验证Python代码所打印的值与C代码选择的值相同.

Below is an example C program that demonstrates the technique. Note that main() runs a simple Python script that calls the included C function GetRandomNumber(). GetRandomNumber() chooses a random number and prints its value to stdout, and then returns it to the Python script. 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.

#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

这篇关于C ++和Boost.Python-如何将变量公开给python并循环更新?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆