Nim
Nim copied to clipboard
DLLs compiled with --tlsEmulation:off can not be loaded with LoadLibraryEx
# mymod.nim
echo "hi"
# test.nim
{.emit:"""
#include <windows.h>
""".}
proc test() =
var hDLL: pointer
{.emit: """
hDLL = LoadLibraryEx("<<FULL_PATH_TO>>\\mymod.dll", NULL,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
""".}
echo "isNil: ", hDLL.isNil
test()
nim c --app:lib --threads:on --tlsEmulation:off mymod
nim c -r test
Output:
isNil: true
Changing tlsEmulation
to on
produces output:
hi
isNil: false
EDIT: In case of failure, GetLastError
is ERROR_MOD_NOT_FOUND (0x7E).
@yglukhov
- please report
GetLastError
refs https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror - can't the more portable std/dynlib be used instead of raw OS calls?
please report GetLastError
Updated description
can't the more portable std/dynlib be used instead of raw OS calls?
nim's loadLib
seems to work fine, but Python 3.9.1 is using LoadLibraryEx
to load modules.
see https://devblogs.microsoft.com/oldnewthing/20131127-00/?p=2553 which provides more info on how to debug ERROR_MOD_NOT_FOUND
; it could be that a dependent dll can't be found
I'm afraid i'm not much of a windows user to dig it. But hopefully the sample should be easy enough to debug for anyone with a proper windows machine.
nim's loadLib seems to work fine, but Python 3.9.1 is using LoadLibraryEx to load modules. It seems that
LoadLibrary
works.
import os
{.emit:"""
#include <windows.h>
""".}
proc test() =
var hDLL: pointer
{.emit: """
hDLL = LoadLibrary("d:\\qqpcmgr\\desktop\\Nim\\foo.dll");
""".}
echo osLastError()
echo "isNil: ", hDLL.isNil
test()
Or loadLibray
doesn't provide flags parameters, it also works. I think some dlls may be not searched.
This works too
import os
{.emit:"""
#include <windows.h>
""".}
proc test() =
var hDLL: pointer
{.emit: """
hDLL = LoadLibraryEx("d:\\qqpcmgr\\desktop\\Nim\\foo.dll", NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
""".}
echo osLastError()
echo "isNil: ", hDLL.isNil
test()
As reported by @cer1969, --tlsEmulation:off
causes the final binary to depend on __emutls_get_address
symbol from libgcc_s_seh-1.dll
.
Compiling the binary with --passL:-static
helps. Maybe consider adding it to global nim.cfg
.
EDIT: s/library/binary
Compiling the library with
--passL:-static
helps. Maybe consider adding it to globalnim.cfg
.
This works and only add 37 kb to the library. Thanks