Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
guides:machine_code [2024-01-02 14:51] – Add section 5, Callback to AHK geek | guides:machine_code [2024-01-02 16:18] (current) – Add section 6, Importing functions geek | ||
---|---|---|---|
Line 211: | Line 211: | ||
- If beta //were// to be called, //it doesn' | - If beta //were// to be called, //it doesn' | ||
- | Traditional MCode tools like MCode4GCC do nothing to address these problems. Instead, you would have to compile and load each function separately, managing and passing around | + | Traditional MCode tools like MCode4GCC do nothing to address these problems. Instead, you have to compile and load each function separately, managing and passing around |
+ | |||
+ | <runner ahk2> | ||
+ | alpha := MCode(' | ||
+ | beta := MCode(' | ||
+ | MsgBox DllCall(beta, | ||
+ | |||
+ | MCode(mcode) { | ||
+ | static e := Map(' | ||
+ | if (!regexmatch(mcode, | ||
+ | return | ||
+ | if (!DllCall(" | ||
+ | return | ||
+ | p := DllCall(" | ||
+ | if (c=" | ||
+ | DllCall(" | ||
+ | if (DllCall(" | ||
+ | return p | ||
+ | DllCall(" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This kind of workaround is not necessary when using MCL, which uses its built-in linker and loader to automatically identify function offsets and adjust the MCode at run-time so that references to other functions resolve correctly instead of remaining '' | ||
For code that defines multiple functions to be called from AHK, those functions must be // | For code that defines multiple functions to be called from AHK, those functions must be // | ||
Line 335: | Line 357: | ||
Although there are many things you can do with MCode, sometimes it is helpful or even necessary to callback to AutoHotkey for some actions. For example, it can be extremely valuable to call back to AutoHotkey for OutputDebug, | Although there are many things you can do with MCode, sometimes it is helpful or even necessary to callback to AutoHotkey for some actions. For example, it can be extremely valuable to call back to AutoHotkey for OutputDebug, | ||
- | AutoHotkey provides a tool to export its own functions to be consumed as a callback from C/C++ APIs, [[https:// | + | AutoHotkey provides a tool to export its own functions to be consumed as a callback from C/%%C++%% APIs, [[https:// |
<runner ahk2> | <runner ahk2> | ||
Line 390: | 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, | ||
+ | |||
+ | 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 '' | ||
+ | |||
+ | <runner ahk2> | ||
+ | #Requires AutoHotkey v2.0 | ||
+ | |||
+ | if !(hDll := DllCall(" | ||
+ | throw OSError(,, " | ||
+ | if !(pFunction := DllCall(" | ||
+ | throw Error(,, " | ||
+ | |||
+ | ;double hypotenuse(double (*sqrt)(double), | ||
+ | ; return sqrt(a * a + b * b); | ||
+ | ;} | ||
+ | lib := MCode(" | ||
+ | |||
+ | MsgBox DllCall(lib, | ||
+ | |||
+ | MCode(mcode) { | ||
+ | static e := Map(' | ||
+ | if (!regexmatch(mcode, | ||
+ | return | ||
+ | if (!DllCall(" | ||
+ | return | ||
+ | p := DllCall(" | ||
+ | if (c=" | ||
+ | DllCall(" | ||
+ | if (DllCall(" | ||
+ | return p | ||
+ | DllCall(" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | When working with MCL, importing functions like this can be handled automatically by the '' | ||
+ | |||
+ | <runner ahk2> | ||
+ | #Requires AutoHotkey v2.0 | ||
+ | #include <MCL> | ||
+ | |||
+ | lib := MCL.FromC(" | ||
+ | ( | ||
+ | #include < | ||
+ | MCL_IMPORT(double, | ||
+ | |||
+ | double hypotenuse(double a, double b) { | ||
+ | return sqrt(a * a + b * b); | ||
+ | } | ||
+ | )") | ||
+ | |||
+ | MsgBox DllCall(lib, | ||
+ | </ | ||
+ | |||
+ | 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: | ||
===== Compatibility Notes ===== | ===== Compatibility Notes ===== | ||