首先介绍一下我在使用Firebreath做些什么。
然后,假设主视图和平面视图都被加载命名为'mainviewer'和'planview',我将把文档附加到计划查看器,如下所示,
planview.attach(mainviewer.doc);
(the signature is "bool attach(const FB::JSObjectPtr& myDoc)" and
The mainviewer.doc is just a firebreath JSAPI)
ISSUE是在firefox中,通过调用传递的JSObject不能被识别为JSAPI
FB::JSAPIPtr jsAPI = myDoc->getJSAPI(); // THIS WILL RETURN **NULL**.
m_main_doc = FB::ptr_cast<LcFbViewerDocumentAPI>(jsAPI); // Cast to my document API.
此问题仅在主机浏览器为firefox,IE / Chrome运行良好时才会发生。
那么,使用firefox时传递的JSAPI会发生什么?
答案 0 :(得分:4)
事实证明,大多数浏览器(包括FireFox)在将NPObject传递给另一个函数调用之前将其包装起来;因此,您无法获得最初传递给浏览器的底层C ++类。因为FireBreath无法访问真正的NPJavascriptObject(FireBreath用来包装JSAPI对象以提供给浏览器的NPObject),所以它无法访问原始的JSAPI对象。
考虑为JSAPI对象的每个实例创建一个静态id。然后,您可以将instance_id公开为JSAPI属性,然后创建一个全局std :: map,您可以使用该地图存储地图以获取对象。
// in the class def
static int counter;
int instance_id;
// In the .cpp file
int MyPluginAPI::counter(0);
std::map<int, FB::JSAPIWeakPtr> apiMap;
FB::JSAPIPtr getJSAPIObjectById(int id) {
std::map<int, FB::JSAPIWeakPtr> fnd = apiMap.find(id);
if (fnd != apiMap.end()) {
return fnd.second->lock(); // it's a weak pointer, lock to get the shared_ptr
} else {
return FB::JSAPIPtr(); // Alternately throw an exception
}
}
MyPluginAPI::MyPluginAPI() {
instance_id = counter++;
// Note that you can't get at the shared_ptr in the constructor,
// so you'll have to call an init function after creating the JSAPI object
registerProperty("instance_id",
make_property(this,
&FBTestPluginAPI::get_instId));
}
int MyPluginAPI::get_instId() { return instance_id; }
void MyPluginAPI::init() {
apiMap[instance_id] = shared_from_this();
}
如果您没有通过地图并清除过期的弱ptrs,这当然会最终泄漏少量内存,但它应该能够满足您的需求。当你得到一个应该是JSAPIPtr对象的对象时,你可以期待它作为JSObjectPtr。
void doSomethingWithAnAPI(const FB::JSObjectPtr& obj) {
if (obj) {
int id = obj->GetProperty("instance_id");
FB::JSAPIPtr ptr = getJSAPIObjectById(id);
if (ptr) {
// Hurray! We have the object
}
}
}
我没有测试过上面的代码,但它应该非常接近。