使用嵌入式Python调用对象实例的函数
我希望能够在我的应用程序中运行Python脚本,以允许自动化内容和修改现有对象/调用现有对象的方法 在我的应用程序中,有一个使用嵌入式Python调用对象实例的函数,python,c++,c++11,boost,Python,C++,C++11,Boost,我希望能够在我的应用程序中运行Python脚本,以允许自动化内容和修改现有对象/调用现有对象的方法 在我的应用程序中,有一个BasicWindow类和从前者派生的MainWindow类。现在,在应用程序启动时,我初始化了main窗口的一个实例。这个对象有很多函数,其中有一个加载文件(LoadFile()),我将在这里使用它作为示例 假设我想调用该特定对象实例的特定函数(但不限于该函数,它只是我想从Python实现的功能的一个示例) 这种方法不是静态的。为此,我使用了Boost.Python,并以
BasicWindow
类和从前者派生的MainWindow
类。现在,在应用程序启动时,我初始化了main窗口的一个实例。这个对象有很多函数,其中有一个加载文件(LoadFile()
),我将在这里使用它作为示例
假设我想调用该特定对象实例的特定函数(但不限于该函数,它只是我想从Python实现的功能的一个示例)
这种方法不是静态的。为此,我使用了Boost.Python,并以这种方式创建了一个模块:
BOOST_PYTHON_MODULE(MyModule)
{
MainWindow::PythonExpose(); //not really sure how to operate here
//more stuff
}
我的想法是,我可以从Python调用如下内容:
MainWindow.LoadFile()
或者更好,只是:
LoadFile()
一种解决方案是创建静态的、应用程序范围的函数,然后只公开这些函数。在C++中,我可以找到<代码>主窗口< /C> >的具体实例:(两种方法都是静态的)
有可能做到这一点吗?一般的问题是:是否可以从Python中调用现有对象的方法(在C++中)?如果是,怎么做?如果没有,我可以做什么来模仿这种行为
例如,我可以轻松地在我的C#应用程序中启用脚本功能,并共享现有对象的实例。(当然C#有反射)。如果您可以保证对象的寿命与使用它的脚本运行的时间一样长,那么我可以使用一种相当简单的方法
我将使用基本计数器类进行演示:
class counter
{
public:
counter() : count(0) {}
void increment() { ++count; }
int count;
};
现在,我将这个类公开给python,这样它就认为它是不可复制的,并且不允许构造新实例。我还公开了我想从脚本中使用的任何成员
BOOST_PYTHON_MODULE(example)
{
bp::class_<counter, boost::noncopyable>("Counter", bp::no_init)
.def("increment", &counter::increment)
;
}
现在,您的脚本可以使用此实例:
c.increment()
示例程序:
#include <boost/python.hpp>
#include <iostream>
namespace bp = boost::python;
// Simple counter that can be incremented
class counter
{
public:
counter() : count(0) {}
void increment() { ++count; }
int count;
};
// Expose the counter class to Python
// We don't need constructor, since we only intend to use instance
// already existing on the C++ side
BOOST_PYTHON_MODULE(example)
{
bp::class_<counter, boost::noncopyable>("Counter", bp::no_init)
.def("increment", &counter::increment)
;
}
int main()
{
Py_InitializeEx(0);
// Bind our class
initexample();
counter c;
bp::object main_module(bp::import("__main__"));
bp::object main_namespace(main_module.attr("__dict__"));
// Add the current instance of counter to Python as attribute c of the main module
main_module.attr("c") = bp::object(bp::ptr(&c));
std::cout << "Before: " << c.count << '\n';
// Increment the counter from Python side
bp::exec("c.increment()", main_namespace);
std::cout << "After: " << c.count << '\n';
Py_Finalize();
return 0;
}
是的,无论是您建议的方式,还是您公开类(没有构造函数,只是您需要的函数),都可以创建一个引用现有实例的python对象(使用指针——例如bp::object(bp::ptr(&foo))
),然后将其推送到解释器,以便您的脚本可以使用它。
c.increment()
#include <boost/python.hpp>
#include <iostream>
namespace bp = boost::python;
// Simple counter that can be incremented
class counter
{
public:
counter() : count(0) {}
void increment() { ++count; }
int count;
};
// Expose the counter class to Python
// We don't need constructor, since we only intend to use instance
// already existing on the C++ side
BOOST_PYTHON_MODULE(example)
{
bp::class_<counter, boost::noncopyable>("Counter", bp::no_init)
.def("increment", &counter::increment)
;
}
int main()
{
Py_InitializeEx(0);
// Bind our class
initexample();
counter c;
bp::object main_module(bp::import("__main__"));
bp::object main_namespace(main_module.attr("__dict__"));
// Add the current instance of counter to Python as attribute c of the main module
main_module.attr("c") = bp::object(bp::ptr(&c));
std::cout << "Before: " << c.count << '\n';
// Increment the counter from Python side
bp::exec("c.increment()", main_namespace);
std::cout << "After: " << c.count << '\n';
Py_Finalize();
return 0;
}
Before: 0
After: 1