[a108] #DllLoad/DllCall fails to automatically resolve func name Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
lvalkov
Posts: 58
Joined: 08 Mar 2019, 16:39

[a108] #DllLoad/DllCall fails to automatically resolve func name

20 Apr 2020, 14:24

DllCall#Performance wrote:If DllCall's first parameter is a literal string such as "MulDiv" and the DLL containing the function is ordinarily loaded ("resides in User32.dll, Kernel32.dll, ComCtl32.dll, or Gdi32.dll") before the script starts, or has been successfully loaded with #DllLoad, the string is automatically resolved to a function address.
Emphasis mine. In the following snippet, a DLL is #DllLoaded successfully, yet DllCall fails to resolve the name of the exported function:

Code: Select all

#DllLoad ucrtbase.dll
MsgBox DllCall('abs', 'Int', -42) ; Call to non-existent function.
Explicitly specifying which DLL the function belongs to yields the desired result:

Code: Select all

#DllLoad ucrtbase.dll
MsgBox DllCall('ucrtbase\abs', 'Int', -42) ; 42
Going by the documentation, it stands to reason that the first code snippet shouldn't result in this particular exception being thrown.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [a108] #DllLoad/DllCall fails to automatically resolve func name

21 Apr 2020, 03:47

DllFile may be omitted when calling a function that resides in User32.dll, Kernel32.dll, ComCtl32.dll, or Gdi32.dll.
User avatar
lvalkov
Posts: 58
Joined: 08 Mar 2019, 16:39

Re: [a108] #DllLoad/DllCall fails to automatically resolve func name  Topic is solved

21 Apr 2020, 19:27

Having now examined the source more closely, I can tell that there is, indeed, no implementation (yet?) for looking up the names of functions in #DllLoaded modules.
The remark in the documentation ("Performance" section) is misleading. Is such a feature in the works? It seems useful and not too overly costly, performance-wise.

I'm using the following patch in the interim, though it's based on the STL:

Code: Select all

// globaldata.h/cpp
#include <vector>
extern std::vector<HMODULE> g_DllLoadedDlls;

// script.cpp
g_DllLoadedDlls.emplace_back(hmodule);

// script2.cpp
std::find_if(
	g_DllLoadedDlls.begin(), 
	g_DllLoadedDlls.end(), 
	[&function, &function_name](const auto module)
	{
		return function = static_cast<void*>(GetProcAddress(module, function_name));
	});
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a108] #DllLoad/DllCall fails to automatically resolve func name

22 Apr 2020, 11:12

Is such a feature in the works?
There is no implementation and (most probably) no intention to implement this, because it is a bad idea. Perhaps it is likely that the dlls for which you can omit the name will never share two functions with the same name, but if you start to add more dlls to this list you will likely run in to trouble eventually. If anything, I'd recommend you always specify which dll you are using.
The remark in the documentation ("Performance" section) is misleading
The text you quoted has nothing to do with omitting the name, it's about a load time optimisation. The documentation for #dllload says nothing about this imagined feature either. Feel free to suggest an improvement to the docs if you have one though.

Cheers.
User avatar
lvalkov
Posts: 58
Joined: 08 Mar 2019, 16:39

Re: [a108] #DllLoad/DllCall fails to automatically resolve func name

24 Jun 2020, 18:50

Helgef wrote:
22 Apr 2020, 11:12
There is [...] no intention to implement this, because it is a bad idea.
I cannot help but disagree with that conclusion of yours. Taken to the extreme, perhaps, it very well might be. Then again, that is universally true of almost anything. It is a matter of trade-offs with respect to convenience, performance and robustness. If it truly were a bad idea, the already implemented (standard DLLs) feature wouldn't have existed to begin with. Clearly, there is some merit to having it.

Weigh the likelihood of collisions occurring, taking into consideration case-sensitivity, parameter types and count, and the average number of mapped DLLs per AutoHotkey script. While it is undeniable that collisions may, in fact, occur, is that enough of a compelling reason to warrant throwing the baby out with the bathwater?

A good deal of APIs out there often choose to prefix annotate their exports with the library's name, which results in a noisy, somewhat redundant, pattern of the form DllCall('MyFooBarLibrary.dll\MyFooBarLibrary_Function', ...). Omitting the DLL name here would pose little to no danger at all as far as disambiguation is concerned. Moreover, library authors and overly paranoid / defense-oriented clients may still opt to fully qualify their functions.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a108] #DllLoad/DllCall fails to automatically resolve func name

25 Jun 2020, 05:19

If it truly were a bad idea, the already implemented (standard DLLs) feature wouldn't have existed to begin with.
The four standard DLLs are all from the same API set, and are very unlikely to ever export two different functions with the same name from different files. (But you do have to be careful when omitting the A/W suffix, since there are cases like SHGetFileInfo, which has its ANSI version exported as SHGetFileInfoA and SHGetFileInfo.) If you further expand that to other standard Windows DLLs, there are functions exported by the same name from different DLLs, but they redirect to the same code.
taking into consideration [...] parameter types and count
How does it help to consider parameters? Generally functions are exported with C linkage; i.e. just a name. There is no function overloading in C or DllCall; if they have the same name, there is a conflict. Having a different parameter count might help to detect the error, but only for stdcall (x86). Even if the parameter types are the same, even if the purpose of the function is the same, it won't necessarily be safe to use in conjunction with other functions that are present in one of the conflicting DLLs but not the other.

That aside, I agree with your overall argument. Also, another reason to allow this convenience is that Windows API sets have stupidly long names. For example, the functions for dealing with Windows Runtime strings are like this:

Code: Select all

WindowsGetString(hstr, ByRef len := 0) {
	p := DllCall("api-ms-win-core-winrt-string-l1-1-0.dll\WindowsGetStringRawBuffer"
		, "ptr", hstr, "uint*", len, "ptr")
	return StrGet(p, -len, "UTF-16")
}
If #DllLoad adds every DLL to the list, the further toward the end of the list a DLL gets, the longer it will take to resolve its functions. Without load-time optimization, this could be quite costly. With it, the cost will be only once per DllCall call site, rather than each time DllCall is called.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a108] #DllLoad/DllCall fails to automatically resolve func name

26 Jun 2020, 12:47

Code: Select all

DllCall("api-ms-win-core-winrt-string-l1-1-0.dll\WindowsGetStringRawBuffer"
This is self-documenting code :thumbsup:.

Cheers.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: Google [Bot], LepG, Panaku and 31 guests