Why doesn't Strawberry Perl call my DllMain?
-
02-07-2021 - |
Question
I'm trying to port Win32::Setupsup, a rather crusty old C++-based module intended to work with Visual C++, to Strawberry Perl and the MinGW GCC that it uses. I've pretty much got it working except for one thing.
The C++ part of the module has a DllMain
function that runs some initialization code at DLL_PROCESS_ATTACH
and cleanup code at DLL_PROCESS_DETACH
. When I compile the module with Visual C++, that works fine. But when I compile it with the MinGW GCC that Strawberry Perl uses, DllMain
is never called.
I think the problem is just that DllMain
is not properly identified as the DLL's entry point when compiled with gcc
. But I don't know how to fix that.
The work-in-progress is in my GitHub repo for Win32::Setupsup. While I use Dist::Zilla to manage releases, you don't actually need dzil
to test it. Just clone the repo, perl Makefile.PL
, and dmake test
.
Solution
Looking at your code, you have
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD reason, LPVOID reserved);
in a C++ source file. Because this is a C++ function, G++ mangles the name to something like __Z7DllMainP11HINSTANCE__mPv@12
, and it cannot be found when the library is loaded.
To solve this, use extern "C"
, either on the function declaration
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD reason, LPVOID reserved);
or in a block
extern "C" {
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD reason, LPVOID reserved);
}
to ensure that the function is given C linkage (avoiding C++ name mangling).