I wanna to use NPAPI plugin in my app and i created a functions, provides by a browser to plugin. Load library, initialization and start, all goes well, until it comes to a function NPP_New. This function makes crash, because NPP pointer (tried instead to specify 0 - the function returns an error code 2 "Invalid Instance" and not crash). I think there is a problem in memory access.Found several ways of memory sharing, but I do not know exactly what is appropriate in this case.
// ...
char szMimeType[] = "application/x-some-plugin";
NPP_t npp; npp.pdata = 0; npp.ndata = &npp;
UINT result = NPP_New(szMimeType, &npp, NP_FULL, 0, 0, 0, NULL);
// ...
#Georg Fritzsche, you were right! The problem was in pointers to NPN_ functions. Variable NPNetscapeFuncs pNpnFuncs create and fill as a local in one of my functions and thus destroyed on completion of the function. When I did pNpnFuncs global variable - everything was fine work.
Related
TLDR: Could someone explain how to correctly use the SymGetTypeInfo.
My goal is to get the type information for local variables (wherever Rip/Eip happens to be).
According to the documentation, I need to call the SymSetContext with the IMAGEHLP_STACK_FRAME structure filled with appropriate values. I got this part working as when I call SymEnumSymbols (setting the BaseOfDll parameter to 0 as the doc says to do when setting context), I do in fact only get the local variables.
HOWEVER:
When inside the enumerate symbols callback, I try to call SymGetTypeInfo, something like this:
static BOOL s_enum_symbols_callback(
PSYMBOL_INFO pSymInfo,
ULONG SymbolSize,
PVOID UserContext) {
// ...
HANDLE hProcess = /*Defined elsewhere*/;
wchar_t *buffer = (wchar_t *)allocate_symname_memory();
SymGetTypeInfo(hProcess, pSymInfo->ModBase, pSymInfo->TypeIndex, TI_GET_SYMNAME, &buffer);
}
SymGetTypeInfo fails with error 1 ("Incorrect function").
Ok so now I am troubleshooting to figure out why this might happen. My first theory is that this may have something to do with setting the context, so I remove the SymSetContext and enumerate again. This time (I obviously get all the symbols), and I get the same problem except for a few types, notably: I am able to get the type of __scrt_current_native_startup_state (which is __scrt_native_startup_state).
Ok so maybe... the problem is that I am calling SymGetTypeInfo inside a Sym* callback function?? (doubt it though). Anyway, I put the theory to the test, and enumerate just the symbols which I have defined globally:
wchar_t global_variable = 12;
int global_variable0 = 12;
float global_variable1 = 12.0f;
int global_variable2 = 12;
Once again, not setting the context, I enumerate the symbols and note the TypeIndex value for each so that once outside of the enumerate symbols function, I call SymGetTypeInfo like this:
SymGetTypeInfo(hProcess, process_pdb_base, type_index, TI_GET_SYMNAME, &buffer);
(process_pdb_base is returned from SymModuleLoad64).
And I get the SAME problem.
Maybe I am completely misunderstanding what the TypeIndex really is? (although it is consistent for different variables with the same type), or maybe it's only for user-defined types??
So yeah I am lost and tired, please help internet.
Alright guys, I think I figured it out and it's all thanks to this marvelous article written in 2004, by Oleg Starodumov!
And one of my theories wasn't completely wrong - I did indeed misunderstand what the Debug Help (well actually, the entire Win32 API!) library refers to, when using the word "type". As the article wonderfully puts it: "The type of an object defines the set of properties supported by the object, and the set of possible relationships between the object and other objects."
So really, the SymGetTypeInfo functions, is just used to query information about any symbol. Now there are indeed different categories of symbols, which are encapsulated by the SymTagEnum enumerator type which is defined in DbgHelp.h IF you have _NO_CVCONST_H defined with #define (NOTE: You use this if you don't have access to cvconst.h which was my case).
Because this article is so great and I don't want to spoil it for anyone, I will quickly resume what I needed to do to fix my issue, instead of trying to explain querying the C/C++ "type" information (not Win32 "type") of a variable.
The first thing I needed to do, was get the tag of the symbol which represented the C/C++ "type" of the local variable symbol (which is indeed stored in TypeIndex). Next, I needed the code to act accordingly for each different possible tag. In my case, because this was what was called a BaseType, I needed to query what BaseType the type symbol was. With this:
SymGetTypeInfo(hProcess, pSymInfo->ModBase, pSymInfo->TypeIndex, TI_GET_BASETYPE, &type);
Now, each base type has a corresponding enum constant associated with it. The enum looks like this:
enum BasicType
{
btNoType = 0,
btVoid = 1,
btChar = 2,
btWChar = 3,
btInt = 6,
btUInt = 7,
btFloat = 8,
btBCD = 9,
btBool = 10,
btLong = 13,
btULong = 14,
btCurrency = 25,
btDate = 26,
btVariant = 27,
btComplex = 28,
btBit = 29,
btBSTR = 30,
btHresult = 31
};
And lo and behold, the base type did in fact correspond with the types of my local variables!
NOTE
I couldn't find this enum in my system (most likely because I didn't have the Debugger Interface Access SDK), so to get it, I simply copied the TypeInfoStructs.h file located in another link provided by Oleg Starodumov.
I'm updating my V1 cocos2d-x app to V3 and I'm stuck on callbacks.
I can do call backs with lambdas like this, works fine -
auto mcb = CallFunc::create([this](){
this->doCallback(kEVENT_MENU_IS_ONSCREEN);
});
hex->runAction(Sequence::create(somethingthattakestime, mcb, NULL) );
However, I want to pass a CallFunc variable into a function, store it in my object, then use/call it at some point in the future.
In a class I define -
CallFunc * callfunc;
Set with a simple -
item->callfunc = callfunc;
Within a function -
void LBMenuAddMenuItemName( CallFunc * callfunc );
I also declare the CallFunc variable as static so it hangs around -
static auto doSoloPlay = CallFunc::create([this](){
CCLOG("doSoloPlay variable");
this->menuSoloPlay();
});
Later when I wish to use this, I do -
Sequence * seq = Sequence::create(callfunc,NULL);
somesprite->runAction(seq);
However, this ends badly with a SIGSEGV (GLThread).
Using typeid(callfunc).name() shows that callfunc is a CallFunc. Using setTag(69) in declaration and then getTag() before SIGSEGV does not return a sensible value.
Can someone explain what I'm doing wrong and the correct method for delayed callbacks?
Thank you!
LB
Tried many things then found this error goes away when I do a 'retain()' after the declaration -
doSoloPlay->retain();
This increases the reference count.
I don't quite know why I need this. My guess is that cocos2d-x classes may do some clever garbage collection?
If the function is called later as a callback, you need to retain the callback when you save it and release it at the right time.
The static declaration only save the address of your CCCallFunc but the class is destroyed before you wish to execute it.
I've built the Qt+Bonjour integration demo from Qt Quarterly, but one thing I can't wrap my head around is that a single call to DNSServiceProcessResult() is calling the DNSServiceResolveReply callback function twice.
It should be calling it once! What I mean is, this single line:
DNSServiceErrorType err = DNSServiceProcessResult(dnssref);
Results in the DNSServiceResolveReply callback I passed to DNSServiceResolve to be called twice.
The interfaceIndex is different - first time it is 10000010, second time it is 20, but I have no idea what that means.
All other parameters are the same between calls (except flags, of course, which is kDNSServiceFlagsMoreComing the first time and 0 the second).
Edit
This is how I call the DNSServiceResolve function.
DNSServiceErrorType err = DNSServiceResolve(&dnssref, 0, 0,
record.serviceName.toUtf8().constData(),
record.registeredType.toUtf8().constData(),
record.replyDomain.toUtf8().constData(),
(DNSServiceResolveReply)bonjourResolveReply, this);
I found the problem, it was that I was passing 0 for the interfaceIndex when calling DNSServiceResolve.
The docs say that:
If this resolve call is
as a result of a currently active DNSServiceBrowse() operation, then the
interfaceIndex should be the index reported in the DNSServiceBrowseReply
callback. If this resolve call is using information previously saved
(e.g. in a preference file) for later use, then use interfaceIndex 0, because
the desired service may now be reachable via a different physical interface.
I'm trying to create a dll that contains a VCL data module - the idea being that various applications can all load the same dll and use the same database code.
The data module itself is tested ok as part of an application - I've copied the form over to my dll project.
So in the dll entry point method, I need to initialize the data module:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
//if I don't call this, I get an exception on initializing the data module
CoInitialize(NULL);
//initialize a standard VCL form; seems to works fine
//I'm not using Application->CreateForm as I don't want the form to appear straight away
if(!MyForm) MyForm = new TMyForm(Application);
//this doesn't work - the thread seems to hang in the TDataModule base constructor?
//I've also tried Application->CreateForm; same result
if(!MyDataModule) MyDataModule = new TMyDataModule(Application);
}
I've also seen something about how I need to call Application->Initialize before creating the form but this doesn't seem to make any difference.
Any ideas?
Thanks
You really should not be doing very much work in your DllEntryPoint() at all. Certainly not calling CoInitialize(), anyway. It is not the DLL's responsibility to call that when loaded. It is the calling app's responsibility before loading the DLL.
You should either:
export an additional function to initialize your DLL and then have the app it after loading the DLL (same for uninitialing the DLL before unloading it)
don't create your TForm/TDataModule until the first time the DLL actually needs them.
move your TForm/TDataModule into their own worker thread inside the DLL. In this case, you would then call CoIniitalize().
And in all cases, don't relay on the DLL's Application object to manage the lifetime of your TForm/TDataModule. Free them yourself instead before the DLL is unloaded.
I've successfully loaded a C++ plugin using a custom plugin loader class. Each plugin has an extern "C" create_instance function that returns a new instance using "new".
A plugin is an abstract class with a few non-virtual functions and several protected variables(std::vector refList being one of them).
The plugin_loader class successfully loads and even calls a virtual method on the loaded class (namely "std::string plugin::getName()".
The main function creates an instance of "host" which contains a vector of reference counted smart pointers, refptr, to the class "plugin". Then, main creates an instance of plugin_loader which actually does the dlopen/dlsym, and creates an instance of refptr passing create_instance() to it. Finally, it passes the created refptr back to host's addPlugin function. host::addPlugin successfully calls several functions on the passed plugin instance and finally adds it to a vector<refptr<plugin> >.
The main function then subscribes to several Apple events and calls RunApplicationEventLoop(). The event callback decodes the result and then calls a function in host, host::sendToPlugin, that identifies the plugin the event is intended for and then calls the handler in the plugin. It's at this point that things stop working.
host::sendToPlugin reads the result and determines the plugin to send the event off to.
I'm using an extremely basic plugin created as a debugging plugin that returns static values for every non-void function.
Any call on any virtual function in plugin in the vector causes a bad access exception. I've tried replacing the refptrs with regular pointers and also boost::shared_ptrs and I keep getting the same exception. I know that the plugin instance is valid as I can examine the instance in Xcode's debugger and even view the items in the plugin's refList.
I think it might be a threading problem because the plugins were created in the main thread while the callback is operating in a seperate thread. I think things are still running in the main thread judging by the backtrace when the program hits the error but I don't know Apple's implementation of RunApplicationEventLoop so I can't be sure.
Any ideas as to why this is happening?
class plugin
{
public:
virtual std::string getName();
protected:
std::vector<std::string> refList;
};
and the pluginLoader class:
template<typename T> class pluginLoader
{
public: pluginLoader(std::string path);
// initializes private mPath string with path to dylib
bool open();
// opens the dylib and looks up the createInstance function. Returns true if successful, false otherwise
T * create_instance();
// Returns a new instance of T, NULL if unsuccessful
};
class host
{
public:
addPlugin(int id, plugin * plug);
sendToPlugin(); // this is the problem method
static host * me;
private:
std::vector<plugin *> plugins; // or vector<shared_ptr<plugin> > or vector<refptr<plugin> >
};
apple event code from host.cpp;
host * host::me;
pascal OSErr HandleSpeechDoneAppleEvent(const AppleEvent *theAEevt, AppleEvent *reply, SRefCon refcon) {
// this is all boilerplate taken straight from an apple sample except for the host::me->ae_callback line
OSErr status = 0;
Result result = 0;
// get the result
if (!status) {
host::me->ae_callback(result);
}
return status;
}
void host::ae_callback(Result result) {
OSErr err;
// again, boilerplate apple code
// grab information from result
if (!err)
sendToPlugin();
}
void host::sendToPlugin() {
// calling *any* method in plugin results in failure regardless of what I do
}
EDIT: This is being run on OSX 10.5.8 and I'm using GCC 4.0 with Xcode. This is not designed to be a cross platform app.
EDIT: To be clear, the plugin works up until the Apple-supplied event loop calls my callback function. When the callback function calls back into host is when things stop working. This is the problem I'm having, everything else up to that point works.
Without seeing all of your code it isn't going to be easy to work out exactly what is going wrong. Some things to look at:
Make sure that the linker isn't throwing anything away. On gcc try the compile options -Wl -E -- we use this on Linux, but don't seem to have found a need for it on the Macs.
Make sure that you're not accidentally unloading the dynamic library before you've finished with it. RAII doesn't work for unloading dynamic libraries unless you also stop exceptions at the dynamic library border.
You may want to examine our plug in library which works on Linux, Macs and Windows. The dynamic loading code (along with a load of other library stuff) is available at http://svn.felspar.com/public/fost-base/trunk/
We don't use the dlsym mechanism -- it's kind of hard to use properly (and portably). Instead we create a library of plugins by name and put what are basically factories in there. You can examine how this works by looking at the way that .so's with test suites can be dynamically loaded. An example loader is at http://svn.felspar.com/public/fost-base/trunk/fost-base/Cpp/fost-ftest/ftest.cpp and the test suite registration is in http://svn.felspar.com/public/fost-base/trunk/fost-base/Cpp/fost-test/testsuite.cpp The threadsafe_store holds the factories by name and the suite constructor registers the factory.
I completely missed the fact that I was calling dlclose in my plugin_loader's dtor and for some reason the plugins were getting destructed between the RunApplicatoinEventLoop call and the call to sendToPlugin. I removed dlclose and things work now.