The best way is actually to extend NPObject with a field to save the associated NPP instance, and provide the allocate/deallocate functions with your NPClass definition. You can then cast the NPObject to your subtype to access the actual NPP instance.
I would NOT recommend doing this at a global level (NP_GetEntryPoints, etc.) as suggested above, as there are potentially several instances of your plugin loaded - maybe even on the same page - and you want to be sure you're invoking the correct one. Unfortunately there seems to be a lot of sample code out there where some random instance is just kept in a global variable, and updated as much as possible.
As an example, assuming C++, you'll want to extend NPObject:
struct MyNPObject : public NPObject {
NPP npp_;
explicit MyNPObject(NPP npp) : npp_(npp) {}
};
Then your NPClass definition will need to have allocate and deallocate definitions:
static NPClass obj_Class = {
NP_CLASS_STRUCT_VERSION,
&obj_allocate,
&obj_deallocate,
NULL,
&obj_hasMethod,
&obj_invoke,
...
Which could be implemented like so:
static NPObject* obj_allocate(NPP npp, NPClass *aClass)
{
return new MyNPObject(npp);
}
static void obj_deallocate(NPObject *obj)
{
delete obj;
}
And when you need to call NP_Invoke, assuming you have the NPObject* (inside obj_invoke, for example) you just downcast:
MyNPObject* myObj = reinterpret_cast<MyNPObject*>(obj);
g_browser->invoke(myObj->npp, ...)