Hi,
I'm currently attempting to create a DLL with a custom DLLMain function in Nim. Based on this forum post , I created the DLL as follows:
import winim/lean
proc NimMain() {.cdecl, importc.}
proc DllMain(hinstDLL: HINSTANCE, fdwReason: DWORD, lpvReserved: LPVOID) : BOOL {.stdcall, exportc, dynlib.} =
if fdwReason == DLL_PROCESS_ATTACH:
NimMain()
return true
This works fine when compiled with the standard MinGW backend (although I'm not entirely sure why NimMain is still exported from the resulting DLL since I haven't used .dynlib?), however I I decided to try it with using MSVC as the backend compiler and ran into an issue:
PS> nim c -d:release --gc:orc --app:lib -d:useMalloc --nomain test.nim
Hint: used config file '<...>\.choosenim\toolchains\nim-1.4.2\config\nim.cfg' [Conf]
Hint: used config file '<...>\.choosenim\toolchains\nim-1.4.2\config\config.nims' [Conf]
Hint: used config file '<...>\orcdll\nim.cfg' [Conf]
...............................CC: test.nim
@mtest.nim.c
<...>\nimcache\test_r\@mtest.nim.c(92): error C2375: 'NimMain': redefinition; different linkage
<...>\nimcache\test_r\@mtest.nim.c(34): note: see declaration of 'NimMain'
Error: execution of an external compiler program 'vccexe.exe /c --platform:amd64 /nologo /O2 /I<...>\.choosenim\toolchains\nim-1.4.2\lib /I<...>\orcdll /nologo /Fo<...>\nimcache\test_r\@mtest.nim.c.obj <...>\nimcache\test_r\@mtest.nim.c' failed with exit code: 2
Based on previous experience with MSVC I'm guessing this has to do with calling conventions/name mangling, but haven't investigated fully. Wanted to ask, though, is this expected behavior when using --nomain? Is there a workaround?
This is because the first declaration of NimMain that MSVC sees has no dllexport attribute. Try to declare it as follows:
proc NimMain() {.cdecl, importc, exportc, dynlib.}
this workaround works but it also rely on assumption about how the codegen works, may not works in the future.
when defined(vcc):
{.emit: "N_LIB_EXPORT N_CDECL(void, NimMain)(void);".}
else:
proc NimMain() {.cdecl, importc.}
proc DllMain(hModule: HANDLE, reasonForCall: DWORD, lpReserved: LPVOID): WINBOOL {.stdcall, exportc, dynlib.} =
case reasonForCall
of DLL_PROCESS_ATTACH:
when defined(vcc):
{.emit: "NimMain();".}
else:
NimMain()
...