Code: Select all
/*
AHK v2 (64-bit) LIBTCC by oif2003 (16 Dec 2018)
This script allows the use of C code within AHK. C code is compiled and loaded into
memory using libtcc.dll. Function pointers are used for DllCall.
Requires TCC: https://download.savannah.gnu.org/releases/tinycc/tcc-0.9.27-win64-bin.zip
Place script in TCC folder or locate it when prompted. (or set tcc.__defPath)
For more information on TCC: https://bellard.org/tcc/
*/
#singleinstance force
;----------------------------
;define C functions with strings
string1 := new tcc('
(
#include <wchar.h>
wchar_t* hello() {
return L"hello world";
}
)'
)
MsgBox(DllCall(string1["hello"], 'Str'))
haystack := "The quick brown fox jumps over the lazy dog." ,tcc.__StrPutVar(haystack, _haystack)
needles := "high" ,tcc.__StrPutVar(needles, _needles)
string2 := new tcc('
(
#include <string.h>
int match(char *haystack, char *needles) {
int r = strpbrk(haystack, needles) - haystack + 1;
return r > 0 ? r : 0;
}
)'
)
pos := DllCall(string2["match"], 'Str', _haystack, 'Str', _needles)
MsgBox('Found "' SubStr(haystack, pos, 1) '" at position ' pos ' in haystack: "' haystack '" using needles: "' needles '"')
;---------------------------
;define C functions in comment blocks
comment1 := new tcc(parseC("Block 1"))
;block tags ("Block 1" here) must not be followed by anything other than a new line
/*_C Block 1
#include <math.h>
int inc() {
static int i = 0;
return ++i;
}
double Csqrt(double x) {
return sqrt(x);
}
*/
MsgBox("Csqrt(" format("{:.3g}", x := 3.14**2) ")"
. " ~ " format("{:.3g}", DllCall(comment1["Csqrt"], 'Double', x, 'Double'))
)
;save function pointer to variable for speed
f := comment1["inc"], t := A_TickCount
loop 1000000
x := DllCall(f)
MsgBox("x = " x " (Time elapsed: " A_TickCount - t " ms)" )
;explicitly include User32.dll so MessageBox will work
comment2 := new tcc(parseC("Block 2"),,, "C:\Windows\System32\User32.dll")
/*_C Block 2
#include <stdio.h>
#include <windows.h>
int hello(char name[]) {
char buf[256];
snprintf(buf, sizeof buf, "Hello %s!", name);
MessageBox(0, buf, "Greeting", 0);
}
*/
DllCall(comment2["hello"], 'AStr', A_UserName)
;===============================================================================================================
parseC(tag := "", path:="") { ;reads C code between labels
static script, lastpos := 1
return (
path := path ? path : A_ScriptFullPath
,startLabel := "/*_" "C " tag "`r"
,endLabel := "*/"
,script || script := fileRead(A_ScriptFullPath)
,cStart := InStr(script, startLabel, ,lastpos) + StrLen(startLabel)
,lastpos++ := cEnd := InStr(script, endLabel, , cStart + 1)
,SubStr(script, cStart, cEnd - cStart)
)
}
class tcc {
static __defPath := A_ScriptDir
,__instanceCount := 0
,__hModule := 0
__New(cStr, tccPath := "", opts := "", addfiles*) { ;opts: literal option string, addfiles := variadic array of paths
static _path := ""
,tcc_add_file := 0x1B2B4
,tcc_compile_string := 0x1CF83
,tcc_free := 0x2FC4
,tcc_new := 0xF703
,tcc_relocate := 0x1C71C
,tcc_set_options := 0xD8E5
,tcc_set_output_type := 0xF5A9
,TCC_OUTPUT_MEMORY := 1
,TCC_RELOCATE_AUTO := 1
tccPath := _path ? _path : (tccPath ? tccPath : tcc.__defPath)
while !FileExist(tccPath "\libtcc.dll")
_path := (tccPath := DirSelect(, , "Locate TCC folder. Close to exit.")) ? tccPath : ExitApp()
(tcc.__hModule) || tcc.__hModule := DllCall("LoadLibrary", 'Str', tccPath "\libtcc.dll", 'Ptr')
,libtcc := tcc.__hModule
,context := DllCall(libtcc + tcc_new, 'Ptr')
,(opts) && (this.__StrPutVar(opts, options), DllCall(libtcc + tcc_set_options, 'Ptr', context, 'Str', options))
for _, v in addfiles
this.__StrPutVar(v, filename), DllCall(libtcc + tcc_add_file, 'Ptr', context, 'Str', filename)
DllCall(libtcc + tcc_set_output_type, 'Ptr', context, 'UInt', TCC_OUTPUT_MEMORY, 'Int')
,this.__StrPutVar(cStr, _cStr), DllCall(libtcc + tcc_compile_string, 'Ptr', context, 'Str', _cStr, 'Int')
,DllCall(libtcc + tcc_relocate, 'Ptr', context, 'Ptr', TCC_RELOCATE_AUTO, 'Int')
,this.__context := context
,this.__symbols := {}
,tcc.__instanceCount++
}
__Get(f) {
static tcc_get_symbol := 0x80E2
return (
this.__symbols[f] ? (
this.__symbols[f]
):(
this.__StrPutVar(f, _f)
,this.__symbols[f] := DllCall(tcc.__hModule + tcc_get_symbol, 'Ptr', this.__context, 'Str', _f, 'Ptr')
)
)
}
__Delete() {
static tcc_delete := 0xD543
DllCall(tcc.__hModule + tcc_delete, 'Ptr', this.__context)
,(--tcc.__instanceCount == 0) && DllCall("FreeLibrary", 'Ptr', tcc.__hModule)
}
__StrPutVar(ByRef str, ByRef var) {
return (VarSetCapacity(var, StrPut(str, "UTF-8")), StrPut(str, &var, "UTF-8"))
}
}