如何使用 boost 和 Firebreath 从 python 中正确触发浏览器事件
首先我必须说,作为一名 Python 程序员,我可能会从错误的角度看待这个问题,自从我在大学写最后一个 C++ 代码以来已经过去很多年了。
我在尝试使用 firebreath 创建混合 python/c++ 插件时遇到了一些问题。到目前为止,我已经成功地使用 boost/python.h 集成了所有部分,但是当我尝试从 python 内部触发事件时出现了问题。我偶然发现了必须将 python 函数与 c++ 函数绑定在一起的问题(使用 BOOST_PYTHON_MODULE)。首先,我尝试直接将 python 与我的 JSAPI 派生类 fbtestconpythonAPI 绑定,这种方法的问题似乎是缺乏对浏览器实例化的 JSAPI 对象的引用,给我带来了 python 函数和 c++ 等效项之间的各种签名不匹配问题执行时间。
我解决这个问题的唯一方法(我同意,是一个丑陋肮脏的解决方案),是使用一个全局指针,我用 set_pluginPointer 手动初始化它。到目前为止,这实际上效果很好,但我知道这不是正确的方法。我读到我不应该在 JSAPI 对象中使用“原始”指针,但我不确定如何针对此特定实现将其替换为共享指针。另一个问题是全局变量,它在所有实例中共享,例如导致所有事件在最后打开的选项卡/窗口上触发。解决后者的一种方法是创建某种数组,其索引为当前窗口/线程 ID,我应该能够从 JSAPI 对象和 python/c++ 函数访问它。
当然,我持开放态度,并且非常感谢任何有关如何改进/修复此特定解决方法的建议,或者更好的是,如何在不进行黑客攻击的情况下交流 boost::python 和 firebreath 的正确方法。
以下是插件代码的相关部分
// Global pointer to plugin instance
fbtestconpythonAPI *fbtestPtr;
void fbtestconpythonAPI::set_pluginPointer(const std::string& val){
m_testString = val;
fbtestPtr = this; //Global pointer initialization
}
void echo(std::string x){
// Firing the echo event on the plugin instance using the global raw pointer
fbtestPtr->fire_echo(x, 1);
}
BOOST_PYTHON_MODULE(Pointless) {
def("echo", echo);
}
FB::variant fbtestconpythonAPI::echo(const FB::variant& msg){
int result_value;
Py_Initialize();
try {
initPointless(); // initialize Pointless
PyRun_SimpleString("import Pointless");
PyRun_SimpleString("Pointless.echo('hello world')");
object module(handle<>(borrowed(PyImport_AddModule("__main__"))));
object dictionary = module.attr("__dict__");
} catch (error_already_set) {
PyErr_Print();
}
Py_Finalize();
return 0;
}
first I must say that as a Python programmer, I might be seeing this problem from a wrong perspective, many years had passed since I wrote my last c++ code back in college.
I'm having a bit of a problem, trying to create a hybrid python/c++ plugin using firebreath. I've been succesfull so far integrating all the parts using boost/python.h, but a problem arose when I tried to fire an event from within python. I stumbled with the problem of having to bind together a python function with a c++ function (using the BOOST_PYTHON_MODULE). First I tried to bind directly python with my JSAPI derived class fbtestconpythonAPI, the problem with this approach seems to be the lack of reference to the JSAPI object instantiated by the browser, giving me all kinds of signature mismatch problems between python function and c++ equivalent at execution time.
The only thing that ocurred to me to fix this( I agree, is an ugly dirty solution), is to use a global pointer which I initialize by hand with set_pluginPointer. This actually works pretty well so far, but I know it is not the right way to do it. I read that I should not be using a "raw" pointer with a JSAPI object, but I'm not sure how to replace it with a shared_ptr for this particular implementation. Another problem is the global variable, wich is shared accross all instances, causing for example, that all events are fired on the last tab/window opened. One way to solve the latter would be creating some sort of array with an index being the current window/thread id, wich is something I should be able to access from both my JSAPI object and python/c++ function.
Of course I'm open, and will apreciate very much, any suggestions, on how to improve/fix either this particular workaround or, better, the correct way to communicate boost::python and firebreath without hacking.
Below is the relevant part of the plugin code
// Global pointer to plugin instance
fbtestconpythonAPI *fbtestPtr;
void fbtestconpythonAPI::set_pluginPointer(const std::string& val){
m_testString = val;
fbtestPtr = this; //Global pointer initialization
}
void echo(std::string x){
// Firing the echo event on the plugin instance using the global raw pointer
fbtestPtr->fire_echo(x, 1);
}
BOOST_PYTHON_MODULE(Pointless) {
def("echo", echo);
}
FB::variant fbtestconpythonAPI::echo(const FB::variant& msg){
int result_value;
Py_Initialize();
try {
initPointless(); // initialize Pointless
PyRun_SimpleString("import Pointless");
PyRun_SimpleString("Pointless.echo('hello world')");
object module(handle<>(borrowed(PyImport_AddModule("__main__"))));
object dictionary = module.attr("__dict__");
} catch (error_already_set) {
PyErr_Print();
}
Py_Finalize();
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
快速浏览一下,您可以像这样设置导出类:
然后您可以传递 对 Python 的 C++ 实例的引用,允许您调用其上的函数,从而触发事件。
From a quick look you'd setup your class for export like this:
Then you can pass a reference to your C++ instance to Python, allowing you to call functions on it which in turn can fire events.