Its my first time writing DLLs and as the title suggests I am trying to import my DLL in Excel however I ran into a brick Wall with stdcall written on it. Here is a minimal example of my problem: My C++ DLL defines the functions
extern "C" __declspec(dllexport) BOOL testBool1() {
return true;
}
extern "C" __declspec(dllexport) BOOL __stdcall testBool2() {
return true;
}
extern "C" __declspec(dllexport) BOOL __stdcall testBool3(BOOL a) {
return a;
}
extern "C" __declspec(dllexport) BOOL testBool4(BOOL a) {
return a;
}
in VBA I try to import them using
Declare Function testBool1 Lib "MyDLL" () As Boolean
Declare Function testBool2 Lib "MyDLL" () As Boolean
Declare Function testBool3 Lib "MyDLL" (ByVal a As Boolean) As Boolean
Declare Function testBool4 Lib "MyDLL" (ByVal a As Boolean) As Boolean
Sub Test()
testBool1
testBool2
testBool3 (True)
testBool4 (True)
End Sub
- testBool1 works just fine
- testBool2 gives a 453 error (Can't find DLL entry point)
- testBool3 gives a 49 error (Bad DLL calling convention)
- testBool4 gives a 453 error (Can't find DLL entry point)
What I think is going on is:
- Excel expects the stdcall convention. However if the function has no parameters it doesnt matter whether its stdcall or cdecl, therefore testBool1 works and testBool3 does not.
- Putting the __stdcall in C++ prevents VBA from finding the function, hence the 453 Error for testBool2 and testBool4.
What can i do to fix this? In my problem I can not change the VBA code only the C++ code.
Update: it seems like the c++ compiler is adding a '_' to the functions with __stdcall, the DLL contains ".testBool1._testBool2@[email protected]". This only happens when compiling to a 32 bit DLL. With a 64 Bit DLL there should be no problem, unfortunately I do not have a 64 Bit Excel right now to verify.
Its my first time writing DLLs and as the title suggests I am trying to import my DLL in Excel however I ran into a brick Wall with stdcall written on it. Here is a minimal example of my problem: My C++ DLL defines the functions
extern "C" __declspec(dllexport) BOOL testBool1() {
return true;
}
extern "C" __declspec(dllexport) BOOL __stdcall testBool2() {
return true;
}
extern "C" __declspec(dllexport) BOOL __stdcall testBool3(BOOL a) {
return a;
}
extern "C" __declspec(dllexport) BOOL testBool4(BOOL a) {
return a;
}
in VBA I try to import them using
Declare Function testBool1 Lib "MyDLL" () As Boolean
Declare Function testBool2 Lib "MyDLL" () As Boolean
Declare Function testBool3 Lib "MyDLL" (ByVal a As Boolean) As Boolean
Declare Function testBool4 Lib "MyDLL" (ByVal a As Boolean) As Boolean
Sub Test()
testBool1
testBool2
testBool3 (True)
testBool4 (True)
End Sub
- testBool1 works just fine
- testBool2 gives a 453 error (Can't find DLL entry point)
- testBool3 gives a 49 error (Bad DLL calling convention)
- testBool4 gives a 453 error (Can't find DLL entry point)
What I think is going on is:
- Excel expects the stdcall convention. However if the function has no parameters it doesnt matter whether its stdcall or cdecl, therefore testBool1 works and testBool3 does not.
- Putting the __stdcall in C++ prevents VBA from finding the function, hence the 453 Error for testBool2 and testBool4.
What can i do to fix this? In my problem I can not change the VBA code only the C++ code.
Update: it seems like the c++ compiler is adding a '_' to the functions with __stdcall, the DLL contains ".testBool1._testBool2@[email protected]". This only happens when compiling to a 32 bit DLL. With a 64 Bit DLL there should be no problem, unfortunately I do not have a 64 Bit Excel right now to verify.
Share Improve this question edited Mar 28 at 14:15 user30093107 asked Mar 28 at 13:25 user30093107user30093107 133 bronze badges 3 |2 Answers
Reset to default 1When compiling for a 32-bit target (which your use of stdcall
implies), the compiler will decorate the names of the exported functions absent instructions to the contrary. For a cdecl
function it will prepend an underscore, and for stdcall
it will additionally append an @
symbol and the number of bytes of arguments (a rudimentary way of making sure you don't use mismatched declarations and trash the stack).
If you had control of the VBA, you could use the Alias
directive to tell it the decorated names. Without control of the VBA, the only alternative is to use a module definition file, which will tell the linker to override the standard name decoration.
The definition file will look like this:
LIBRARY "MyDLL.dll"
EXPORTS
testBool1
testBool2
testBool3
testBool4
There are quite a few additional things that can be done with module definition files which aren't relevant to your application. The format is documented by Microsoft here: https://learn.microsoft/en-us/cpp/build/reference/module-definition-dot-def-files?view=msvc-170
Note that accounting for name decoration is only relevant for 32-bit compiling, as in 64-bit stdcall was eliminated and name decorations are not included for C-format function names. However, it won't hurt to continue to include the module definition file.
As Craig said creating a .def solves the problem
LIBRARY MyDll
EXPORTS
testBool1
testBool2
testBool3
testBool4
You can use
dumpbin /EXPORTS myDll.dll
to get a list of the function names (In Visual Studio I can run the command in Tools->Command Line -> Developer Command Prompt).
@
character followed by the number of bytes of arguments (and note that stdcall is only applicable for 32-bit and goes away for 64-bit). – Craig Commented Mar 28 at 14:10BOOL
is four bytes andBoolean
is two. They also have different representation ofTRUE
(1
and-1
respectively). And you are using parentheses when you shouldn't. – GSerg Commented Mar 28 at 14:49BOOL
vsBoolean
, I believe the correct representation of the VB Boolean type in C++ isVARIANT_BOOL
, where the true value isVARIANT_TRUE
. – Craig Commented Mar 28 at 15:23