I like those ideas! It's a good way to get our feet wet. I have taken a few C courses in college in the past but I don't remember much from it aside from doing a lot of pointer arithmetic (not fun )
As it turns out, it was a configuration issue. I was able to call MessageBox after explicitly including User32.dll using "libtcc\tcc_add_file". The command line option variant does not work. Here's the latest working copy I have that takes options(opts) and includes(addfiles*) as parameters (addfiles is variadic)
Edit: fixed typo in tcc_set_options
Spoiler
Code: Select all
;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.
#singleinstance force
path := A_ScriptDir
;----------------------------
;define a C function string
string1 := new tcc('
(
char* hello() {
return "hello world";
}
)', path)
msgbox(DllCall(string1["hello"], "AStr"))
haystack := "The quick brown fox jumps over the lazy dog."
needle := "fly"
tcc.__StrPutVar(haystack, _haystack)
tcc.__StrPutVar(needle, _needle)
string2 := new tcc('
(
#include <string.h>
int match(char *haystack, char *needle) {
int r = strpbrk(haystack, needle)-haystack+1;
return r > 0 ? r : 0;
}
)', path)
msgbox( 'Found a char from: "' needle '" in "' haystack '" at position: '
. DllCall( string2["match"], "Str", _haystack, "Str", _needle ) )
;---------------------------
;define a C comment block
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;
}
int sqrt3(double *d) {
*d = sqrt(3);
}
*/
DllCall(comment1["sqrt3"], "Ptr", &_sqrt := 0.0)
msgbox("sqrt(3) = " _sqrt)
;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:="") {
return (
path := path ? path : A_ScriptFullPath
;read c code
,startLabel := "`n/*_" "C " tag "`r"
,endLabel := "`n*/"
,script := fileRead(A_ScriptFullPath)
,cStart := InStr(script, startLabel) + StrLen(startLabel) + 1
,cEnd := InStr(script, endLabel, , cStart + 1)
,SubStr(script, cStart, cEnd - cStart)
)
}
class tcc {
__New(cStr, tccPath := "", opts := "", addfiles*) { ;opts: literal option string, addfiles := variadic array of paths
static _path := ""
tccPath := _path ? _path : tccPath
while !FileExist(tccPath "\libtcc.dll")
_path := tccPath := DirSelect(, , "Locate TCC folder")
cStr := (InStr(cStr, "main(") ? "" : "int main() {return 0;}`n") cStr
,tccPath := tccPath ? tccPath : A_ScriptDir
,hModule := DllCall("LoadLibrary", "Str", tccPath "\libtcc.dll", "Ptr")
,context := DllCall("libtcc\tcc_new", "Ptr"), DllCall("libtcc\tcc_add_library_path", "Ptr", context, "Str", libraryPath, "Int")
,this.__StrPutVar(tccPath "\lib", libraryPath), DllCall("libtcc\tcc_add_library_path", "Ptr", context, "Str", libraryPath, "Int")
,this.__StrPutVar(tccPath "\include", includePath), DllCall("libtcc\tcc_add_include_path", "Ptr", context, "Str", includePath, "Int")
,this.__StrPutVar(tccPath "\include", sysincludePath), DllCall("libtcc\tcc_add_sysinclude_path", "Ptr", context, "Str", sysincludePath, "Int")
,this.__StrPutVar(tccPath, tcclibPath), DllCall("libtcc\tcc_set_lib_path", "Ptr", context, "Str", tcclibPath)
,(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 := 1, "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 := 1, "Int")
,this.context := context, this.hModule := hModule, this.symbols := {}
}
__Get(fStr) {
return (
this.symbols[fStr] ?(
this.symbols[fStr]
):(
this.__StrPutVar(fStr, _fStr)
,this.symbols[fStr] := DllCall("libtcc\tcc_get_symbol", "Ptr", this.context, "Str", _fStr, "Ptr")
)
)
}
__Delete() {
DllCall("libtcc\tcc_delete", "Ptr", this.context)
,DllCall("FreeLibrary", "Ptr", this.hModule)
}
__StrPutVar(string, ByRef var, encoding := "cp0") {
return (
VarSetCapacity(var, StrPut(string, encoding) * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
,StrPut(string, &var, encoding)
)
}
}