03-07-2012 04:23 PM
Greetings!
I'm having an issue calling (specifically running) a function in an .obj file from within a .dll.
Right now, it will load the obj file and get a valid (not NULL) pointer to the function, but then I get a general protection fault when I try to call the function. If I mouse over the function pointer, the address is valid (well not NULL anyway) but claims 'unknown function name'.
I'm assuming I'm not exposing the functions on the obj file properly, but the us of __stdcall seems to make no difference.
This is new territory for me so don't assume it's not something obvious that I'm jsut missing!
Any help is aprpeciated
Solved! Go to Solution.
03-07-2012 04:59 PM
So you're using LoadExternalModule and GetExternalModuleAddr? Can you post the lines of code you use to get the function address, store it, and then call it? You're correct to examine the calling convention -- you must make sure the declaration used on the calling side is the same as in the defining module.
Are you sure the access violation is not happening inside the function call? Can you add a MessagePopup or something in the function to see if you are actually entering the function body?
Mert A.
National Instruments
03-08-2012 10:34 AM - edited 03-08-2012 10:36 AM
I've clean up some of the uninteresting bits (error messages that are tripped, etc) - but the piece of code below - doesn't throw an error and seems to associate an address location to CurrentTestPtr
sModuleID = LoadExternalModule ("testobj.obj"); // only load if different name if (sModuleID < 0) { /*Err*/ } else { CurrentTestPtr = GetExternalModuleAddr (sModuleID,"SBIT",&FunctionPtrErr); if (FunctionPtrErr != 0) { /*Err*/ } }
This is the line of code that throws the protection fault. I can see the address, but for a value displays "Unknown Function Name"
(*CurrentTestPtr) (sTestData); /* actually run the test */
The Function it's pointing to (or should be) has been defined as below, then built into "Testobj.obj"
/Header File **************************** void __stdcall SBIT(tTestData *data); void __stdcall VMELoopback(tTestData *data); void __stdcall PINGTest(tTestData *data); void cSBIT(tTestData *data); void cVMELoopback(tTestData *data); void cPINGTest(tTestData *data); //C File **************************** void __stdcall SBIT(tTestData *data) { cSBIT(data); } void __stdcall VMELoopback(tTestData *data) { cVMELoopback(data); } void __stdcall PINGTest(tTestData *data) { cPINGTest(data); }
Because I'm in control of the dll and the application code I can run this all in debug so I'm confident it's the use of the function pointer that causes the crash. This leads me to believe the dll just doesn't have the proper permission to call back into the application. Both projects (dll and application) are set to using the '__stdcall' calling convention
I know this is NOT an ideal way to do things, this is the classic case of trying to inject some positive change into an aging infrastructure, so I'm limited in what I can alter.
I'm basically just trying to replace a static library, that gets compiled into the exe, to a dynamic one, so we can make improvements to that library without having to recompile the exe (so if there's a easier/smarter way to do that, that I've missed I'm all ears)
Thanks for at least responding Mert! It is appreciated!
03-08-2012 12:05 PM
First of all, your code looks correct. This leads me to think it may be a Data Execution Prevention (DEP) issue. The LoadExternalModule/GetExternalModuleAddr mechanism was developed well before DEP was prevalent, and it was obsoleted a long time ago (in favor of LoadLibrary/GetProcAddress). If you go into Window's advanced system settings, there is a button for Performance settings. Click that and it will bring up some tabs, one of which is Data Execution Prevention. Set it to "Turn on DEP for essential Windows programs and services only," reboot the machine, and try your program again.
I realize that even if this solves your problem, it may not be feasible to ensure that DEP is disabled on every machine your program needs to run on. Since you're at the point where you get to choose the path forward, I would strongly recommend that you try to replace the static lib with a DLL. Granted, a DLL must be linked, and it cannot directly access functions and variables in the program; this may make it difficult to adapt the existing static lib code. However, if it really is a separate logical component, it ought to be feasible.
Mert A.
National Instruments
03-12-2012 09:10 AM
Nailed it Merl - thank you! This actually may be a viable solution for my set-up since any PC that would run this solution is on our small manufacturing floor, and would only be implemented on future projects (so an even smaller sub-set of PCs).
This did arise because I'm switching one static lib to a dynamic - and it was the static lib that's using the LoadExternalModule/GetExternalModuleAddr mechanism - to access the .obj file - which then redirects it to the application. oh my!
Anyway, despite the somewhat convoluted linking - your help has gone a LONG way in helping to make some much needed in-roads into how things are done here and I very much appreciate your help!