【问题标题】:Mapping variable argument LISP function to C function - C将变量参数 LISP 函数映射到 C 函数 - C
【发布时间】:2011-06-01 09:24:20
【问题描述】:

我正在开发一个自定义 LISP 解释器。它不支持在 LISP 中定义函数,而是将所有函数映射到 C 函数。当它看到这样的表达式时,

(substr 'input '1 '1)

它知道调用内部substr 函数并返回结果。

现在我计划实现一个message 函数,它支持基本格式并将输出写入stdout。类似的,

(message "Hello, %s" name)

%s 将替换为变量name 中的值。

目前的计划是直接将格式和参数传递给printf 等函数。这样我就可以支持printf支持的所有格式了。但是问题来自可变数量的参数。一种方法是,

if(argcount == 1)
   /* call printf with one arg */
else if(argcount == 2)
   /* call printf with two arg */
....

这可行,但我想知道是否有更好的方法来实现这一目标?

【问题讨论】:

    标签: c lisp interpreter


    【解决方案1】:

    我怀疑有办法做到这一点。原因是您的 lisp 函数的参数数量仅在运行时知道,但 C 函数的参数数量必须在编译时知道。

    这包括 va_lists,除非您想以某种特定于平台的方式破解它们。

    您真正能做的最好的事情就是用 C 语言编写一个函数,该函数能够一次循环一个参数并用它们做一些事情。我能看到的唯一方法是不仅为每个内部函数存储一个函数指针,而且还存储一个“调用约定”,它将提供有关它是否以普通方式获取参数或是否以相当于 va_list。

    像 printf 这样的函数会有一个包装器,比如 printf_wrapper,并且你会存储一个指向包装器的函数指针。此包装器将接受格式字符串作为普通参数,后跟其他参数的列表或数组(大致类似于 va_list)。

    您可以通过将 printf_wrapper 函数的调用约定指定为“va_list_type”来指示 printf_wrapper 以期望列表的参数结束,这意味着它采用通常的固定参数,并且所有剩余的参数必须捆绑并提供将其作为一个列表。

    当然,编写一个 printf_wrapper 函数可以将一个格式字符串拆分并解析为多个格式字符串是一项工作。这是一个我正是这样做的示例,以便我可以添加自己的自定义格式说明符:

    https://github.com/wbhart/bsdnt/blob/v0.26/helper.c

    【讨论】:

      【解决方案2】:

      让您的 C 函数采用类似于argc/argv 的参数。也就是说,取一个指定参数个数的参数,然后是一个指向每个参数的指针列表的指针。

      【讨论】:

      • 我明白这一点。但问题是我必须在内部使用printf 或类似的现有函数。
      • 好吧,vprintf 需要va_list。你认为我可以从参数中创建它吗?
      • @Appu 是的,但这将涉及了解您平台的 va_list 的实现细节。但它是一种与其他任何数据结构一样的数据结构,可以即时生成。
      • @Conrad..我不认为手动创建 va_list 是个好主意,我想不出以独立于平台的方式来做。
      • 好吧,或者自己实现printf。你更喜欢这个主意吗?
      【解决方案3】:

      略好于 if-else 链将是一个开关。

      switch(argcount){
          case 1: printf(arg[0]); break;
          case 2: printf(arg[0],arg[1]); break;
          //etc.
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-17
        • 1970-01-01
        • 2021-03-28
        • 2016-08-08
        • 2011-04-28
        • 2015-05-07
        • 2013-10-18
        • 2017-10-20
        相关资源
        最近更新 更多