На самом деле лучший способ - это расширить NPObject полем, чтобы сохранить связанный экземпляр NPP, и предоставить функции выделения / освобождения с вашим определением NPClass. Затем вы можете привести NPObject к вашему подтипу, чтобы получить доступ к фактическому экземпляру NPP.
Я бы НЕ рекомендовал сделать это на глобальном уровне (NP_GetEntryPoints и т. Д.), Как предложено выше, поскольку потенциально может быть загружено несколько экземпляров вашего плагина - возможно, даже на одной странице - и вы хотите чтобы убедиться, что вы вызываете правильный. К сожалению, существует много примеров кода, где какой-то случайный экземпляр просто хранится в глобальной переменной и обновляется в максимально возможной степени.
В качестве примера, принимая C ++, вы захотите расширить NPObject:
struct MyNPObject : public NPObject {
NPP npp_;
explicit MyNPObject(NPP npp) : npp_(npp) {}
};
Тогда вашему определению NPClass нужно будет иметь определения размещения и освобождения:
static NPClass obj_Class = {
NP_CLASS_STRUCT_VERSION,
&obj_allocate,
&obj_deallocate,
NULL,
&obj_hasMethod,
&obj_invoke,
...
Что может быть реализовано так:
static NPObject* obj_allocate(NPP npp, NPClass *aClass)
{
return new MyNPObject(npp);
}
static void obj_deallocate(NPObject *obj)
{
delete obj;
}
А когда вам нужно вызвать NP_Invoke, предполагая, что у вас есть NPObject * (например, внутри obj_invoke), вы просто понижаетесь:
MyNPObject* myObj = reinterpret_cast<MyNPObject*>(obj);
g_browser->invoke(myObj->npp, ...)