Do I somehow need to tell the lookup in what DLL it should look for this function
Yes, you have to load the library that contains GetCurrentDirectory
, which is Kernel32
(according to the documentation):
System.loadLibrary("Kernel32");
After loading a library with System::load
or System::loadLibrary
, it can be found using the loader lookup (i.e. SymbolLookup.loaderLookup()
). See the documentation:
Returns a symbol lookup for symbols in the libraries associated with
the caller's class loader.
A library is associated with a class loader CL
when the library is
loaded via an invocation of System.load(String)
or
System.loadLibrary(String)
from code in a class defined by CL
. ...
Note that System::loadLibrary
also requires the directory that contains the library to be listed in the java.library.path
system property (you will get an exception if it's not). For Kernel32
this should be C:\Windows\System32
(for a test with printf this was not necessary)?
The reason it works for printf
is because you are using the defaultLookup
of the nativeLinker
which can find all the symbols in the standard C library. GetCurrentDirectory
is not a part of that library though.
Furthermore, it looks like GetCurrentDirectory
is defined as __inline
, which means you can not link against it dynamically, as the symbol/function is simply not present in Kernel32.dll
, AFAICT:
> dumpbin.exe /EXPORTS C:\Windows\System32\kernel32.dll | sls GetCurrentDirectory
555 22A 0001F010 GetCurrentDirectoryA
556 22B 00018CA0 GetCurrentDirectoryW
Instead, you have to look up and call GetCurrentDirectoryA
for char
s or GetCurrentDirectoryW
for wchar_t
s directly:
System.loadLibrary("Kernel32");
SymbolLookup loaderSyms = SymbolLookup.loaderLookup();
MemorySegment addr = loaderSyms.lookup("GetCurrentDirectoryA").orElseThrow();
// use 'addr'