Ok, a "nicer" call_function, done with CoDScript only:
PHP Code:
call_function(function, signature, a, b, c, d, e, f, g, h, i, j, k, l) {
args = [];
args[args.size] = a;
args[args.size] = b;
args[args.size] = c;
args[args.size] = d;
args[args.size] = e;
args[args.size] = f;
args[args.size] = g;
args[args.size] = h;
args[args.size] = i;
args[args.size] = j;
args[args.size] = k;
args[args.size] = l;
buf = memory_malloc(128);
bb = binarybuffer_new(buf);
signatureClean = ""; // without the . (varargs-marker)
for (ii=0; ii<signature.size; ii++)
if (signature[ii] != ".")
signatureClean += signature[ii];
signature_pos = 0;
for (ii=0; ii<args.size; ii++) {
//printf("ii=% type=%\n", ii, getType(args[ii]));
needGuessType = ii >= signatureClean.size;
//printf("ii=%, sigClean.size=% needGuessType=%\n", ii, signatureClean.size, needGuessType);
if ( ! needGuessType) {
// don't guess type when it's given in signature
binarybuffer_write(bb, signatureClean[ii], args[ii]);
continue;
}
type = "";
switch (getType(args[ii])) {
case "INT": type = "i"; break;
case "STRING": type = "s"; break;
case "FLOAT": type = "f"; break;
}
signature += type; // only add missing types to signature
binarybuffer_write(bb, type, args[ii]); // add data with our guessed type
}
//printf("Function: % Signature: %\n", function, signature);
ret = call_function_raw(function, signature, buf);
memory_free(buf);
binarybuffer_free(bb);
return ret;
}
Call like:
PHP Code:
call_function(libc_printf, "s.", "hi!!! int=%d float=%f string=%s\n", 123, 0.345, "yo");
Output (with debug messages):
Code:
ii=0 type=STRING
ii=1 type=INT
ii=2 type=FLOAT
ii=3 type=STRING
ii=4 type=UNDEFINED
ii=5 type=UNDEFINED
ii=6 type=UNDEFINED
ii=7 type=UNDEFINED
ii=8 type=UNDEFINED
ii=9 type=UNDEFINED
ii=10 type=UNDEFINED
ii=11 type=UNDEFINED
Function: -146088352 Signature: s.ifs
hi!!! int=123 float=0.345000 string=yo
Now we only need to declare the "needed" signature "s.", for printf(char *msg, ...), because we can figure out the rest dynamically, based on getType(args[ii]).
Limitation:
We can't use %c (1 byte char) or %g (8 bytes double) without explicit signature, because these types don't exist in CoDScript itself, so there is no way to tell binarybuffer_write() about the type-information only with getType().
For that case, you need to make the signature explicit:
PHP Code:
call_function(libc_printf, "s.ifsdc", "hi!!! int=%d float=%f string=%s double=%g char=%c\n", 123, 0.345, "yo", 0.123, "#");
Output:
Code:
hi!!! int=123 float=0.345000 string=yo double=0.123 char=#
Return values:
Just added this in new commit: https://github.com/kungfooman/libcod...dff68c1ba77ba7
Binaries are updated: http://killtube.org/downloads/libcod/2015.01.17/
PHP Code:
ret = call_function(libc_printf, "s.", "asd\n");
printf("printed chars: %\n", ret);
Output:
Code:
asd
printed chars: 4
Basically that's just eax as int though atm. Some converting based on signature would be nice, like "s.)i" for "return an int".