Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用嵌入式Python调用对象实例的函数_Python_C++_C++11_Boost - Fatal编程技术网

使用嵌入式Python调用对象实例的函数

使用嵌入式Python调用对象实例的函数,python,c++,c++11,boost,Python,C++,C++11,Boost,我希望能够在我的应用程序中运行Python脚本,以允许自动化内容和修改现有对象/调用现有对象的方法 在我的应用程序中,有一个BasicWindow类和从前者派生的MainWindow类。现在,在应用程序启动时,我初始化了main窗口的一个实例。这个对象有很多函数,其中有一个加载文件(LoadFile()),我将在这里使用它作为示例 假设我想调用该特定对象实例的特定函数(但不限于该函数,它只是我想从Python实现的功能的一个示例) 这种方法不是静态的。为此,我使用了Boost.Python,并以

我希望能够在我的应用程序中运行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