I am importing an C++ DLL in an innosetup install script. The DLL code is as follows:
void __stdcall SetFbParam(char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue){
//of no use here and doesn't change anything}
In the Innosetup, I import it using
procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;);
external 'SetFbParam@files:MyDll.dll stdcall setuponly';
However, I always get a runtime error during launch of the installer, saying that it cannot import my dll. I tried it with various calling conventions, but it always fails.
If it's of any importance, I'm running Win7 x64 with UAC on ( the installer requests rights elevation and crashes after that).
The exact message is:
Error
Runtime error (at -1:0):
Cannot import
dll:C:\Users\Nevod\AppData\Local\Temp\is-6LOEC.tmp\MyDll.dll
The dll is there.
Thanks!
Is MyDll.dll 32-bit?
Does MyDll.dll depend on any other DLLs in the same directory? If so, you need to list the name(s) of those DLLs after "MyDll.dll" to ensure that they are extracted before MyDll.dll is loaded, and you likely need the "loadwithalteredsearchpath" option as well. Example from the help:
procedure ADllFunc(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal);
external 'ADllFunc@files:A.dll,B.dll stdcall loadwithalteredsearchpath'; //A.dll depends on B.dll
(I know it is old but maybe some other hits this one too)
Most probably the name of the function is mangled in the C++ DLL. I had the same problem and I was able to solve it by recompiling the dll. In short:
If you export from C++ something like:
void __stdcall foo()
you will get a function called(Visual Studio):
?foo@@YGXXZ
To prevent name mangling you should use export "C" directive. Example (Visual Studio)
extern "C" __declspec( dllexport ) void __stdcall foo()
However I have found that Visual Studio will continue to mangle and you get something like:
_foo@0
The sole way I was able to get clean names is explained here:
C++ DLL Export: Decorated/Mangled names
And the culprit is indeed __stdcall. If you remove that from your declaration:
extern "C" __declspec( dllexport ) void foo()
you will again get a clean export, even without a DEF file. IMO this should be good enough, as the code above declares a "C" exported function and the default calling convention for C is stdcall. However I haven't had the time and disposition to validate this as adding a DEF file is way easier than navigating asm code and check stack pointers :)
In order to use DLLs in InnoSetup's [Code] section please make sure:
- DLL is in 32 bit mode (even if the installer is built for 64bit and is running in 64bit mode)
- exported functions have
extern "C" __declspec( dllexport )
modifier
- use cdecl calling convention because stdcall mangles name (http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx). Of course it is possible to specify mangled name in InnoSetup import statement. But it seems easier to just use cdecl