今天在我的C代码里面使用tcc当脚本,感觉比lua还爽, lua已经够小巧够精制了, Tiny C Compiler 更小, 速度也比lua要快, 关键是还能直接传指针参数或指针的返回值,就和C的函数调用一样方便,用TCC的好处是,我们可以把不变的代码用C来实现,把经常要改变的逻辑等用TCC来实现,这样以后修改逻辑相关的东西就不需要重新编译程序,用TCC最方便的地方就是直接把指针当参数和返回值在脚本和宿主程序之间传来传去。
下面是官方源代码里的一个例子 :
/*
* Simple Test program for libtcc
*
* libtcc can be useful to use tcc as a "backend" for a code generator.
*/
#include
#include
#include
#include "libtcc.h"
/* this function is called by the generated code */
int add(int a, int b)
{
return a + b;
}
char my_program[] =
"int fib(int n)\n"
"{\n"
" if (n <= 2)\n"
" return 1;\n"
" else\n"
" return fib(n-1) + fib(n-2);\n"
"}\n"
"\n"
"int foo(int n)\n"
"{\n"
" printf(\"Hello World!\\n\");\n"
" printf(\"fib(%d) = %d\\n\", n, fib(n));\n"
" printf(\"add(%d, %d) = %d\\n\", n, 2 * n, add(n, 2 * n));\n"
" return 0;\n"
"}\n";
int main(int argc, char **argv)
{
TCCState *s;
int (*func)(int);
s = tcc_new();
if (!s) {
fprintf(stderr, "Could not create tcc state\n");
exit(1);
}
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
tcc_set_lib_path(s, argv[1]+9);
/* MUST BE CALLED before any compilation */
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
if (tcc_compile_string(s, my_program) == -1)
return 1;
/* as a test, we add a symbol that the compiled program can use.
You may also open a dll with tcc_add_dll() and use symbols from that */
tcc_add_symbol(s, "add", add);
/* relocate the code */
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
return 1;
/* get entry symbol */
func = tcc_get_symbol(s, "foo");
if (!func)
return 1;
/* run the code */
func(32);
/* delete the state */
tcc_delete(s);
return 0;
}
下面的代码是我在自己的程序里面使用的例子
int offset = 0;
MatchResult_t Res;
memset (&Res, 0, sizeof(Res));
MatchField_t* pmf = pbq->arrMatch[idx];
TCCState *script;
script = tcc_new();
if (!script)
{
writelog(LOG_ERROR, "Could not create tcc state\n");
return;
}
tcc_set_output_type(script, TCC_OUTPUT_MEMORY);
//编译脚本文件
if (tcc_add_file(script, "./script/hit.c") == -1)
{
writelog (LOG_ERROR, "Compiling error");
tcc_delete(script);
return;
}
//添加内部符号给脚本使用
//tcc_add_symbol(s, "add", add);
// relocate the code
if (tcc_relocate(script, TCC_RELOCATE_AUTO) < 0)
{
tcc_delete(script);
return;
}
//定义函数指针
int (*func)(MatchField_t*, MatchResult_t*, char*, int);
//获取函数地址
func = tcc_get_symbol(script, "hitMatch");
if (!func)
{
tcc_delete(script);
return;
}
//通过函数地址 调用函数
int ret = func(pmf, &Res, vbuf, vsiz);
if(ret == 0)
{
//TODO...
}
tcc_delete(script);
脚本 hit.c 代码如下 :
int hitMatch (MatchField_t* pmf, MatchResult_t* pcr, char* vbuf, int vsiz)
{
memcpy (pcr->dataType, vbuf, sizeof(int));
//TODO....
return 0;
}