关于包装和调用 C 函数
我从这个中文博客 得到这个问题http://chenyufei.info/blog/2011-02-28/wrap-c-function-closure-gcc-nested-function/ 作者想在c语言中使用闭包,他发现GCC具有嵌套函数(和闭包)的能力。 例如:
typedef int (*func_t)(int arg);
int foo(int a) {
return a + 1;
}
func_t create_wrap_function(func_t f) {
int wrapped(int arg) {
// call original function
int val = f(arg);
fprintf(log_func_call, "arg: %d ret: %d", arg, val);
return val;
}
return wrapped;
}
但这不是常见的解决方案。 create_wrap_function 具有固定的函数格式,因为 func_t 限制了格式。
我们知道,Lua有闭包,也可以调用C函数。 我想实现的是: 我们要调用的函数是 foo1 和 foo2,它们具有不同类型的参数和返回值。
int foo1(int a) {
...
return intValue;
}
double foo2(char* str, double a) {
...
return dblValue;
}
在C客户端中,调用该函数如下:
lua_returnValue returnValue1 = Do_Lua_Wrap(__FILE__, __LINE__, foo1, 1);
lua_returnValue returnValue2 = Do_Lua_Wrap(__FILE__, __LINE__, foo2, "string data", 1.2345);
在Do_Lua_Wrap中,它将把foo1和1传递给Lua函数,然后像正常过程一样调用foo1函数。 然后将 foo2 和一个 char* 以及一个 double 值传递给 Lua 函数,然后像正常过程一样调用 foo2 函数。 在Lua函数中,可以记录FILE和LINE的信息 并写一些关于函数参数的额外日志。
但我不知道如何用C和Lua编写函数Do_Lua_Wrap, 是否可以?
如果可以的话,你能给我一些建议吗?
I get this question from this Chinese blog http://chenyufei.info/blog/2011-02-28/wrap-c-function-closure-gcc-nested-function/
The author want to use closure in c language, and he found GCC has the ability of nested function (and closure).
For example:
typedef int (*func_t)(int arg);
int foo(int a) {
return a + 1;
}
func_t create_wrap_function(func_t f) {
int wrapped(int arg) {
// call original function
int val = f(arg);
fprintf(log_func_call, "arg: %d ret: %d", arg, val);
return val;
}
return wrapped;
}
But it is not common solution. create_wrap_function has fixed function format, because the func_t limits the format.
As we know, Lua has closure, and could call C function too.
What I want to implement like:
The functions we want to call is foo1 and foo2, they has different types of args and return value.
int foo1(int a) {
...
return intValue;
}
double foo2(char* str, double a) {
...
return dblValue;
}
In C client, call the function like:
lua_returnValue returnValue1 = Do_Lua_Wrap(__FILE__, __LINE__, foo1, 1);
lua_returnValue returnValue2 = Do_Lua_Wrap(__FILE__, __LINE__, foo2, "string data", 1.2345);
In the Do_Lua_Wrap, it will pass the foo1 and 1 to the Lua function, then call foo1 function like normal process.
Then pass the foo2 and one char* and one double value to the Lua function, then call foo2 function like normal process.
In the Lua function, it could log the information about FILE and LINE
and write some extra log about function arguments.
But I don't have idea about how to write the function Do_Lua_Wrap in C and Lua,
Is it possible?
If possible, could you give me some advices?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您显然对可变参数函数感兴趣,但问题在于确定要推送的参数的类型到 Lua 堆栈上。我会推荐几种方法:
第一种方法是包含
格式化字符串 printf
系列或二进制包装格式
常用于较高级别
语言。例如,看一下
在使用的格式模式
lpack Lua 模块。关键是
扫描格式字符串以
确定数量和类型
提供了参数。
或者,您可以实现
变体类型。每个论点
需要包裹在这样一个
结构。另外,总数量
需要提供论据
作为第一个参数。
最后,您可以分两次传递参数
数组而不是使用可变参数
功能。第一个数组将
包含枚举类型
对应
void的目标
第二个数组中的指针。这种方法需要最多的房子*
保留客户端代码,但是
相当干净。指定数组长度的参数或哨兵
还需要一个或两个数组末尾的值。
希望其中一种方法适合您。就我个人而言,我会选择第一个选项并使用 lpack 代码作为指导。它也最接近您问题中指定的函数签名。
You are obviously interested in a variadic function, but the trouble is determining the type of the arguments to push onto the Lua stack. I'll recommend a couple approaches:
The first would be to include a
format string a la the printf
family or binary packing formats
often used in higher level
languages. For example, take a look
at the format pattern used in the
lpack Lua module. The key is to
scan through the format string to
determine how many and what kind of
arguments are provided.
Alternatively, you could implement a
variant type. Each argument
would need to be wrapped in such a
structure. Also, the total number of
arguments would need to be provided
as the first parameter.
Finally, you could pass arguments in two
arrays instead of using a variadic
function. The first array would
contain the enumerated types
corresponding to the target of
void
pointers in the second array. This method requires the most house*
keeping for client code, but is
fairly clean. Either an argument specifying the length of the arrays or a sentinel
value at the end of one or both array would be required as well.
Hopefully, one of those methods should work out for you. Personally, I would go with the first option and use the lpack code as a guide. It comes the closest to the function signature specified in your question as well.