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 代码中更新 "live" 吗?如果一切都使用一种语言,那将是微不足道的(例如使用全局变量),但在两种环境的边缘,它就变得棘手了。
编辑:
我试图像这样公开变量 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 函数 return 将变量的当前值传递给 Python Python 脚本调用它时的脚本。
下面是一个演示该技术的示例 C 程序。请注意,main()
运行 是一个简单的 Python 脚本,它调用包含的 C 函数 GetRandomNumber()
。 GetRandomNumber()
选择一个随机数并将其值打印到标准输出,然后 return 将其发送到 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
简介
我有一个从 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 代码中更新 "live" 吗?如果一切都使用一种语言,那将是微不足道的(例如使用全局变量),但在两种环境的边缘,它就变得棘手了。
编辑:
我试图像这样公开变量 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 函数 return 将变量的当前值传递给 Python Python 脚本调用它时的脚本。
下面是一个演示该技术的示例 C 程序。请注意,main()
运行 是一个简单的 Python 脚本,它调用包含的 C 函数 GetRandomNumber()
。 GetRandomNumber()
选择一个随机数并将其值打印到标准输出,然后 return 将其发送到 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