Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.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
将不透明数据传递给C++;来自Python的回调_Python_C++_Boost_Boost Python - Fatal编程技术网

将不透明数据传递给C++;来自Python的回调

将不透明数据传递给C++;来自Python的回调,python,c++,boost,boost-python,Python,C++,Boost,Boost Python,我正在将Python(使用boost::Python)嵌入到使用回调的应用程序插件中。基本上,我想做一些事情,比如: namespace bp = boost::python; class state_info_t { }; void register_callback(std::shared_ptr<state_info_t>& state, bp::object& o); { // Access some persistent state informat

我正在将Python(使用boost::Python)嵌入到使用回调的应用程序插件中。基本上,我想做一些事情,比如:

namespace bp = boost::python;

class state_info_t
{
};

void register_callback(std::shared_ptr<state_info_t>& state, bp::object& o);
{
  // Access some persistent state information
}

// Create some persistent state information
std::shared_ptr<state_info_t> state = std::make_shared<state_info_t>();

PyImport_AppendInittab("foo", initfoo);

Py_Initialize();

std::shared_ptr<bp::object> main_module = std::make_shared<bp::object>(bp::handle<>(bp::borrowed(PyImport_AddModule("__main__"))));
bp::object main_namespace = main_module->attr("__dict__");
std::shared_ptr<bp::object> foo_module = std::make_shared<bp::object>(bp::handle<>(PyImport_ImportModule("foo")));

main_namespace["foo"] = *foo_module;

bp::scope foo_scope(*foo_module);

// Both of these fail with _a lot_ of errors, most related to "no matching function call to 'get_signature'
bp::def("register_callback",
        [&](bp::object& o) { register_callback(state, o); },
        bp::arg("func"));

bp::def("register_callback",
        std::bind(register_callback, state, std::placeholders::_1),
        bp::arg("func"));
在Python中(比如test.py):

<>和在C++端登记ReistStEclipse()函数:

void register_callback(boost::python::object& o)
{
    // Access some persistent state information
}

BOOST_PYTHON_MODULE(foo)
{
  boost::python::def("register_callback", register_callback);
}

void library_entry()
{
  PyImport_AppendInittab("foo", initfoo);

  PyInitialize();

  // Create some persistent state information

  boost::python::exec_file("test.py", ...);
}
这里的问题是,我需要创建Python上下文,并将内容存储在返回到应用程序的不透明指针中。当Python调用C++时,我需要恢复不透明值。例如:

// Create some persistent state information
std::shared_ptr<state_info_t> state = std::make_shared<state_info_t>();

PyImport_AppendInittab("foo", initfoo);

Py_Initialize();

std::shared_ptr<bp::object> main_module = std::make_shared<bp::object>(bp::handle<>(bp::borrowed(PyImport_AddModule("__main__"))));
bp::object main_namespace = main_module->attr("__dict__");
std::shared_ptr<bp::object> foo_module = std::make_shared<bp::object>(bp::handle<>(PyImport_ImportModule("foo")));
bp::object foo_namespace = main_module->attr("__dict__");

main_namespace["foo"] = *foo_module;
foo_namespace["state"] = bp::handle<>(state); // Whatever the appropriate wrapper is
应用程序(调用)>我的C++库——(运行)-> python脚本——(调用)>我的C++库

对于最后一步,我需要恢复一些不透明的数据。此外,我需要不透明的数据是持久的。对我的C++库的调用是来自应用程序的回调。我正在解决的问题是想知道如何将该状态信息传递给C++ ReistSyCalbAd()函数。我试过这样的方法:

namespace bp = boost::python;

class state_info_t
{
};

void register_callback(std::shared_ptr<state_info_t>& state, bp::object& o);
{
  // Access some persistent state information
}

// Create some persistent state information
std::shared_ptr<state_info_t> state = std::make_shared<state_info_t>();

PyImport_AppendInittab("foo", initfoo);

Py_Initialize();

std::shared_ptr<bp::object> main_module = std::make_shared<bp::object>(bp::handle<>(bp::borrowed(PyImport_AddModule("__main__"))));
bp::object main_namespace = main_module->attr("__dict__");
std::shared_ptr<bp::object> foo_module = std::make_shared<bp::object>(bp::handle<>(PyImport_ImportModule("foo")));

main_namespace["foo"] = *foo_module;

bp::scope foo_scope(*foo_module);

// Both of these fail with _a lot_ of errors, most related to "no matching function call to 'get_signature'
bp::def("register_callback",
        [&](bp::object& o) { register_callback(state, o); },
        bp::arg("func"));

bp::def("register_callback",
        std::bind(register_callback, state, std::placeholders::_1),
        bp::arg("func"));
我不喜欢最后一个,因为它向脚本公开了状态信息


我不想使状态信息成为全局的,因为可能有多个正在运行的Python实例。不管怎样,对于多个Python实例,我仍然需要一种方法来确定哪个Python实例正在运行,以选择适当的状态信息。

我想我找到了一种方法来实现我想要的

我可以创建一个类,然后将该类的一个实例放入sys.modules中,而不是实际创建一个模块(请参阅)

所以我做了这样的事情:

namespace bp = boost::python;

class foo
{
  public:
    void register_callback(bp::object&);
};

...

// Register foo with Python (in the current scope)
bp::object foo_class = bp::class_<foo>("foo")
  .def("register_callback", &foo::register_callback);

// Get sys.modules
bp::object obj(bp::handle<>(bp::borrowed(PyImport_GetModuleDict())));

// Add an instance of foo to sys.modules
obj["foo"] = foo_class();

这似乎使类实例以模块的形式出现,并以模块的形式工作。

我正在使用的一个选项是使用PyCapsule并将其存储在模块字典中(这是我在最后提到的)。我不确定它是否会起作用,因为我认为模块字典是所有口译员共享的。虽然可能是sys.modules字典。。。
namespace bp = boost::python;

class foo
{
  public:
    void register_callback(bp::object&);
};

...

// Register foo with Python (in the current scope)
bp::object foo_class = bp::class_<foo>("foo")
  .def("register_callback", &foo::register_callback);

// Get sys.modules
bp::object obj(bp::handle<>(bp::borrowed(PyImport_GetModuleDict())));

// Add an instance of foo to sys.modules
obj["foo"] = foo_class();
import foo

def func():
  ...

foo.register_callback(func)