Как я могу связать экземпляр плагина Mozilla со скриптом с его NObject?
Вопрос
Я столкнулся с проблемой, связывающей вызванный метод в плагине, который я пишу, с соответствующим экземпляром плагина.Документация по адресу http://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Scripting_plugins не дает достаточно информации, чтобы быть действительно полезной по этому вопросу.
В двух словах, я пытаюсь понять, какой именно скриптовый объект плагин должен возвращать в ответ на вызов NPP_GetValue с аргументом переменной, равным NPPpluginScriptableNPObject .Я предполагаю, что для каждого экземпляра плагина должен быть экземпляр NPObject, но как метод invoke() в NPClass должен находить экземпляр плагина (NPP) из скриптового NPObject, который указан в качестве аргумента?Я полагаю, я мог бы реализовать таблицу подстановки для этого, но у меня такое чувство, что я упускаю что-то очевидное.
Я сохраняю указатель на экземпляр класса C ++ (экземпляр реализует функциональность плагина) в элементе pdata NPP, в NPP_New().
Решение
Наверное, я сам отвечаю на свой вопрос...
Решение, которое я нашел (и я все равно был бы признателен за комментарии по поводу его обоснованности, особенно если вы считаете, что есть лучший способ сделать это), состояло в том, чтобы выделить производную структуру NPObject, которая имеет указатель на мой класс реализации в функции allocate (), которую я предоставляю Firefox из моего плагина.Затем я сохраняю указатель на этот NPObject в элементе pdata NPP в NPP_New().
В invoke() я приводлю указатель NPObject, который я получаю, к дополнительным элементам производной структуры, чтобы я мог получить указатель на экземпляр класса реализации.
Это, насколько я могу судить, является целью проекта - объекты NPObject являются экземплярами NPClass, на которые они указывают, они реализуют методы и свойства через указатели функций NPClass, которые имеют дело с этими объектами, и ожидается, что любые личные данные будут выделены и освобождены реализацией, и их формат не указан.
Это выглядело бы примерно так:
static NPClass refObject = {
NP_CLASS_STRUCT_VERSION,
My_Allocate,
My_Deallocate,
NULL,
My_HasMethod,
My_Invoke,
My_InvokeDefault,
My_HasProperty,
My_GetProperty,
NULL,
NULL,
};
class MyImplClass {
// Implementation goes here
};
struct MyNPObject : public NPObject {
MyImplClass *my_impl_instance;
};
// This is just a bit of memory management - Mozilla wants us to allocate our own memory:
NPObject *My_Allocate(NPP inst, NPClass *)
{
// We initialize the structure in NPP_New() below
return (NPObject *)malloc(sizeof(MyNPObject));
}
NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
char* argn[], char* argv[], NPSavedData* saved )
{
NPObject *scriptable_object = npnfuncs->createobject(instance, &refObject);
npnfuncs->retainobject(scriptable_object);
MyImplClass *new_player = new MyImplClass();
instance->pdata = scriptable_object;
((MyNPObject*)instance->pdata)->my_impl_instance = new_player;
return NPERR_NO_ERROR;
}