关于包装和调用 C 函数

发布于 2024-10-19 11:30:24 字数 1372 浏览 3 评论 0原文

我从这个中文博客 得到这个问题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函数中,可以记录FILELINE的信息 并写一些关于函数参数的额外日志。

但我不知道如何用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

孤蝉 2024-10-26 11:30:24

您显然对可变参数函数感兴趣,但问题在于确定要推送的参数的类型到 Lua 堆栈上。我会推荐几种方法:

  1. 第一种方法是包含
    格式化字符串 printf
    系列或二进制包装格式
    常用于较高级别
    语言。例如,看一下
    在使用的格式模式
    lpack Lua 模块。关键是
    扫描格式字符串以
    确定数量和类型
    提供了参数。

  2. 或者,您可以实现
    变体类型。每个论点
    需要包裹在这样一个
    结构。另外,总数量
    需要提供论据
    作为第一个参数。

  3. 最后,您可以分两次传递参数
    数组而不是使用可变参数
    功能。第一个数组将
    包含枚举类型
    对应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:

  1. 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.

  2. 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.

  3. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文