将变量参数LISP函数映射到C函数- C

时间:2022-12-15 20:44:44

I am developing a custom LISP interpreter. It won't support defining functions like in LISP, instead all functions are mapped to C functions. When it sees an expression like,

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

(substr 'input '1 '1)

it knows to call internal substr function and return the result.

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

Now I am planning to implement a message function which supports basic formatting and writes the output to stdout. Something like,

现在我计划实现一个消息函数,该函数支持基本的格式化并将输出写到stdout。类似的,

(message "Hello, %s" name)

%s will be replaced with value in variable name.

%s将被替换为变量名的值。

Current plan is to directly pass the format and arguments to functions like printf. In that way, I can support all formats that printf supports. But problem comes with variable number of arguments. One way to do will be something like,

当前的计划是将格式和参数直接传递给printf之类的函数。这样,我就可以支持printf支持的所有格式。但问题是有不同的参数。一种方法是,

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

This works, but I am wondering is there a better way to achieve this?

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

3 个解决方案

#1


2  

I doubt there is a way to do this. The reason is that the number of parameters to your lisp function is only known at runtime, but the number of arguments to a C function must be known at compile time.

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

This includes va_lists unless you want to hack at them in some kind of platform specific way.

这包括va_list,除非您想以某种特定于平台的方式攻击它们。

The best you can really do is write a function in C which is capable of looping through the arguments one at a time and doing something with them. The only way I can see around this is to not only store a function pointer for each of your internal functions, but to also store a "calling convention" which will give information about whether it takes parameters in the ordinary way or whether it finishes with the equivalent of a va_list.

你能做的最好的事情就是用C编写一个函数,它可以一次一个地循环参数,并对它们进行处理。唯一的方法我可以看到在这不仅是存储为每个内部函数的函数指针,但也存储“调用协定”,将会给信息是否需要参数以普通的方式或相当于va_list是否完成。

Functions like printf would have a wrapper, printf_wrapper, say, and you'd store a function pointer to the wrapper. This wrapper would accept the format string as an ordinary parameter, followed by a list or array of other parameters (roughly analogous to a va_list).

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

You might indicate that printf_wrapper finishes with a parameter that expects a list by specifying the calling conventions for the printf_wrapper function as "va_list_type", meaning that it takes the usual fixed parameters, and that all remaining parameters must be bundled up and supplied to it as a list.

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

Of course writing a printf_wrapper function which can split up and parse a format string into multiple format strings is a bit of work. Here's an example of where I did precisely this so that I could add my own custom format specifiers:

当然,编写一个printf_wrapper函数(它可以将一个格式字符串分割并将它解析为多个格式字符串)有点困难。这里有一个例子,我正是这样做的,以便我可以添加我自己的自定义格式说明:

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

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

#2


0  

Have your C function take parameters somewhat like argc/argv. That is, take a parameter specifying the number of parameters, and then a pointer to a list of pointers for each parameter.

让你的C函数使用参数,比如argc/argv。也就是说,取一个指定参数数量的参数,然后取一个指向每个参数的指针列表的指针。

#3


0  

Slightly better than an if-else chain would be a switch.

比if-else链更好的是一个开关。

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

#1


2  

I doubt there is a way to do this. The reason is that the number of parameters to your lisp function is only known at runtime, but the number of arguments to a C function must be known at compile time.

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

This includes va_lists unless you want to hack at them in some kind of platform specific way.

这包括va_list,除非您想以某种特定于平台的方式攻击它们。

The best you can really do is write a function in C which is capable of looping through the arguments one at a time and doing something with them. The only way I can see around this is to not only store a function pointer for each of your internal functions, but to also store a "calling convention" which will give information about whether it takes parameters in the ordinary way or whether it finishes with the equivalent of a va_list.

你能做的最好的事情就是用C编写一个函数,它可以一次一个地循环参数,并对它们进行处理。唯一的方法我可以看到在这不仅是存储为每个内部函数的函数指针,但也存储“调用协定”,将会给信息是否需要参数以普通的方式或相当于va_list是否完成。

Functions like printf would have a wrapper, printf_wrapper, say, and you'd store a function pointer to the wrapper. This wrapper would accept the format string as an ordinary parameter, followed by a list or array of other parameters (roughly analogous to a va_list).

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

You might indicate that printf_wrapper finishes with a parameter that expects a list by specifying the calling conventions for the printf_wrapper function as "va_list_type", meaning that it takes the usual fixed parameters, and that all remaining parameters must be bundled up and supplied to it as a list.

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

Of course writing a printf_wrapper function which can split up and parse a format string into multiple format strings is a bit of work. Here's an example of where I did precisely this so that I could add my own custom format specifiers:

当然,编写一个printf_wrapper函数(它可以将一个格式字符串分割并将它解析为多个格式字符串)有点困难。这里有一个例子,我正是这样做的,以便我可以添加我自己的自定义格式说明:

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

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

#2


0  

Have your C function take parameters somewhat like argc/argv. That is, take a parameter specifying the number of parameters, and then a pointer to a list of pointers for each parameter.

让你的C函数使用参数,比如argc/argv。也就是说,取一个指定参数数量的参数,然后取一个指向每个参数的指针列表的指针。

#3


0  

Slightly better than an if-else chain would be a switch.

比if-else链更好的是一个开关。

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