首先介绍一下我使用 Firebreath 所做的一些背景知识。
- 我正在使用 firebreath 在浏览器中开发渲染查看器插件。
- 我在插件中定义了两种 MIME 类型,一种用于主查看器,另一种用于 2D 平面图。
- 在每个页面中,仅允许一个主查看器,但可以有多个 2D 平面图。它们都共享在主查看器中打开的相同模型文档。
- 因此,在实例化 2D 平面图之后,我需要将文档对象(firebreath JSAPI)传递给 2D 平面图。
然后,假设主查看器和平面图都已加载,命名为“mainviewer”和“planview”,我将把文档附加到平面图查看器,如下所示,
planview.attach(mainviewer.doc);
(the signature is "bool attach(const FB::JSObjectPtr& myDoc)" and
The mainviewer.doc is just a firebreath JSAPI)
问题是在 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发生了什么变化呢?
事实证明,大多数浏览器(包括 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();
}
如果您不遍历映射并清除过期的弱指针,这当然最终会泄漏少量内存,但它应该可以满足您的需要。当您获得一个应该是 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
}
}
}
我还没有测试过上面的代码,但它应该非常接近。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)