Load the same dll multiple times
chaoxi24 opened this issue · comments
Load the same dll multiple times
Autohotkey is a scripting language for the win platform. I use libloading to load autohotkey.dll, which constitutes an independent autohotkey interpreter.
I need to load multiple autohotkey.dll, each of which is a separate thread.
Autohotkey has a built-in method to load multiple dlls:
dll:=fileread("AutoHotkey.dll")
loop 3
{
ahk:=MemoryLoadLibrary(&dll)
ahktextdll:=MemoryGetProcAddress(ahk, "ahktextdll")
DllCall(ahktextdll,"Str","MsgBox test-" a_index,"Str","","Str","")
}
How to use libloading to achieve?
The underlying native APIs (https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw) used by libloading do not support loading multiple instances of the same library.
Load AHK and use its Memory*
APIs, I guess? An alternative option would be to make differently named copies of the AHK dll and load those – that way the reference counting implemented by native APIs won't kick in.
An alternative option would be to make differently named copies of the AHK dll and load those
This is the function of "MemoryLoadLibrary". It directly modifies the name of the dll in the memory, then loads the dll, and reads out the addresses of all functions. Therefore, even if you don't know the name of the dll, you can call the function normally.
From what I can tell that's not at all what the code does – instead they appear to implement an entire custom loader, which is way out of scope for libloading
, at least currently.
From what I can tell that's not at all what the code does – instead they appear to implement an entire custom loader, which is way out of scope for
libloading
, at least currently.
No, this is achieved purely by winapi. Because in the old version, this feature is not built-in, but exists in an .ahk library.
It is not limited to loading AutoHotkey.dll, it can load any dll from memory. I often use it to load python.dll.
Although this may be beyond the scope of libloading, but I still hope that libloading can achieve it. I'm very sorry that I am new to rust, and I don't have a programming foundation, I don't know how to convert it into rust code.
No, this is achieved purely by winapi.
The MemoryLoadLibraryEx
clearly implements an entire custom loader and AFAICT the only reliance on windows APIs is to load transitive library dependencies. It also ends up relying on a number of internal implementation details of the NT/Windows that I'm not sure are stable or intended to be user-visible. It is a horrible hack.
I don't know what they used to do in the past, before this code existed, but if I had to guess, it is something along the lines of making copies of the dll
file in some temporary directory and loading those, much like what I suggested you should do above in this issue.
If you do not want to copy dll
files and load the copies, then the most straightforward way for you to achieve what you want to do is to call the MemoryLoadLibrary
in the first place. You could do this in a couple of different ways. First is by linking to the library normally and calling its functions via FFI. You can do same via libloading too:
let library = libloading::Library::new("whatever_contains_memoryloadlibrary.dll").expect("foo");
let memory_load_library = library.get::<unsafe "C" fn(*const u8, usize, bool)>(b"MemoryLoadLibrary\0").expect("mll");
let copied_library = memory_load_library(...);
Thank you. I think I get it.
But I have another question. If I get the address of a function (e.g. 3222) through memoryloadlibrary, how do I convert this address into a function that can be called in rust? 3222 →??→ rust-func()
thank you for your help.
I will close this now. In the future you may be able to reach a wider community when asking questions on users.rust-lang.org or similar user-oriented forums.