guides:machine_code

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
guides:machine_code [2024-01-02 16:09] – [5. Callback to AHK] Fix unescaped ++ geekguides:machine_code [2024-01-02 16:18] (current) – Add section 6, Importing functions geek
Line 412: Line 412:
  
 It may be tempting to try to use CallbackCreate in order to wrap mathematical functions like Sqrt, however this should be avoided normally because it will absolutely destroy any performance gains that you were aiming to achieve by using MCode in the first place. Instead, native machine code implementations of sqrt and other mathematical functions should be embedded or imported. It may be tempting to try to use CallbackCreate in order to wrap mathematical functions like Sqrt, however this should be avoided normally because it will absolutely destroy any performance gains that you were aiming to achieve by using MCode in the first place. Instead, native machine code implementations of sqrt and other mathematical functions should be embedded or imported.
 +
 +==== 6. Importing Functions ====
 +
 +Writing C or %%C++%% code in an MCode environment, without any access to the standard libraries, can be extremely limiting. These limits can be eased significantly by importing key functions from DLLs that ship with Windows, or from third-party DLLs that you have on hand.
 +
 +The basic strategy is this:
 +
 +  - Load the DLL using AutoHotkey
 +  - Fetch the function pointer using AutoHotkey
 +  - Pass that function pointer using the same strategy we did for CallbackCreate
 +  - Call that function from your MCode
 +
 +For example, we can import ''sqrt'' from ''msvcrt.dll'' in order to do some mathematical calculations:
 +
 +<runner ahk2>
 +#Requires AutoHotkey v2.0
 +
 +if !(hDll := DllCall("GetModuleHandle", "Str", "msvcrt", "Ptr"))
 + throw OSError(,, "Failed to find DLL msvcrt")
 +if !(pFunction := DllCall("GetProcAddress", "Ptr", hDll, "AStr", "sqrt", "Ptr"))
 + throw Error(,, "Failed to find function sprintf from DLL msvcrt")
 +
 +;double hypotenuse(double (*sqrt)(double), double a, double b) {
 +; return sqrt(a * a + b * b);
 +;}
 +lib := MCode("2,x86:8g8QRCQI8g8QTCQQi0QkBPIPWcDyD1nJ8g9YwfIPEUQkBP/g,x64:8g9ZyfIPWdJmDyjB8g9Ywkj/4Q==")
 +
 +MsgBox DllCall(lib, "Ptr", pFunction, "Double", 3.0, "Double", 4.0, "Cdecl Double")
 +
 +MCode(mcode) {
 +  static e := Map('1', 4, '2', 1), c := (A_PtrSize=8) ? "x64" : "x86"
 +  if (!regexmatch(mcode, "^([0-9]+),(" c ":|.*?," c ":)([^,]+)", &m))
 +    return
 +  if (!DllCall("crypt32\CryptStringToBinary", "str", m.3, "uint", 0, "uint", e[m.1], "ptr", 0, "uint*", &s := 0, "ptr", 0, "ptr", 0))
 +    return
 +  p := DllCall("GlobalAlloc", "uint", 0, "ptr", s, "ptr")
 +  if (c="x64")
 +    DllCall("VirtualProtect", "ptr", p, "ptr", s, "uint", 0x40, "uint*", &op := 0)
 +  if (DllCall("crypt32\CryptStringToBinary", "str", m.3, "uint", 0, "uint", e[m.1], "ptr", p, "uint*", &s, "ptr", 0, "ptr", 0))
 +    return p
 +  DllCall("GlobalFree", "ptr", p)
 +}
 +</runner>
 +
 +When working with MCL, importing functions like this can be handled automatically by the ''MCL_IMPORT'' macro. Any standalone loader generated by MCL that has an import like this will automatically include any AHK-side import loading code that would otherwise have to be written manually. Imports done this way are automatically added to the global scope, so they do not have to be passed as a parameter to DllCall.
 +
 +<runner ahk2>
 +#Requires AutoHotkey v2.0
 +#include <MCL>
 +
 +lib := MCL.FromC("
 +(
 +#include <mcl.h>
 +MCL_IMPORT(double, msvcrt, sqrt, (double));
 +
 +double hypotenuse(double a, double b) {
 + return sqrt(a * a + b * b);
 +}
 +)")
 +
 +MsgBox DllCall(lib, "Double", 3.0, "Double", 4.0, "Cdecl Double")
 +</runner>
 +
 +MCL can also be used to import functions from third-party DLLs, such as lua54.dll. For more information about that, please refer to the [[libraries:machine_code:mcl|library page for MCL]].
 ===== Compatibility Notes ===== ===== Compatibility Notes =====