【问题标题】:Pass a string containing a function name and its arguments to another function.将包含函数名称及其参数的字符串传递给另一个函数。
【发布时间】:2012-02-22 21:18:36
【问题描述】:

我想将一个字符串传递给 C 语言中的函数,该函数将解析出函数名称、函数的参数及其数据类型,然后为我调用该函数。最好的方法是什么?

【问题讨论】:

  • “将 [a] 字符串作为函数调用”没有任何意义。
  • 我很乐意提供帮助,但我无法理解您的问题。请修改并重试。
  • @CodyGray 和 Jonathan Henson 我正在处理可变数量的参数。所以对于每个不同的函数调用,我都会得到不同的参数列表,这就是为什么我用所有参数。
  • 你想复制printf()的行为吗?
  • “把字符串变成函数调用”的工具一般是某种编译器。如果要支持通用 C 语法,则需要通用 C 编译器。如果您想支持更有限的语法,那么您必须确切地定义它是什么,并为此编写一个小型编译器。

标签: c string function introspection


【解决方案1】:

如果你想编写一个带有格式字符串和可变参数的函数,例如:

int function(const char* strFormat, ... )
{
  //parse out the format using regex or something
  //then store the data into the variable aruments
  //or create a string concatenating everything
}

就像 printf、sprintf 或 scanf 一样,

那么最好的办法就是看一些好的教程。

http://msdn.microsoft.com/en-us/library/fxhdxye9(v=vs.80).aspx

http://www.cprogramming.com/tutorial/c/lesson17.html

如果您想实际传递要调用的函数的函数名及其参数,则需要在您的 c 代码中实现某种形式的反射或自省,这是一个非常复杂的 switch 语句,它调用函数您基于字符串值,或编写一些复杂的宏来充当辅助 编译器。

glib 的 gobject 是 c 中自省的一个很好的例子。 http://developer.gnome.org/gobject/stable/

没有自省的简单事情可能是:

void* function (const char* strFunctionName, ... )
{
  if(!strcmp(strFunctionName, "functionA"))
  {
    //use va_list to parse out the arguments for the function.
    functionA(//each of the arguments from va_list);
  }
  else if(!strcmp(strFunctionName, "functionB"))
  {
    //use va_list to parse out the arguments for the function.
    functionB(//args from va_list);
  }
  ...
}

如果您有更具体的想法,请在您的问题中说明。

【讨论】:

  • 感谢您的宝贵时间,但您没有得到我的问题。我没有尝试使用可变数量参数的函数。我正在尝试的是假设我有一个字符串 char *str="variance (dArray,p1,p2)".如何将此字符串作为普通函数调用
  • @johnkrishna 使用可变参数将使数据类型及其值的解析比编写极其复​​杂的正则表达式更容易。
  • 再次非常感谢你,但我们似乎在不同的轨道上。在我的场景中,每次字符串都会不断变化,这取决于我收到的参数,所以我只需要如何制作我的C 编译器将我的字符串视为函数调用。
  • @johnkrishna 如果不编写自己的编译器,您就不能。我的三个选项之一是您唯一的选择。您必须编写一个函数来为您执行字符串中指定的函数。例如: const char* strFunction = "MyFunction(a, b)"; ExecuteMyFunctionPlease(strFunction);据我所知,没有办法解决这个问题。
  • 是的,你是绝对正确的。但是如果 strFunction 的值发生变化呢?
【解决方案2】:

我不确定这是否是标准的,但您可以在 C++ 中使用 __PRETTY_FUNCTION__

例如:

void foo(int a, int b)
{
    cout << __PRETTY_FUNCTION__ << endl;
}

输出:

void foo(int, int)

【讨论】:

    【解决方案3】:

    如果你想做:

    char *funct = "foo(bar)";
    

    要实际调用函数foo(),那么这是不可能的,C 就是不能那样工作。我建议:

    a) 您坐下来重新考虑您的应用程序,因为任何事情都不需要这种行为。

    b) 尝试具有这种能力的语言,例如objective-c

    c) 如果你真的、真的、真的想这样做……然后制作一个字符串解析器和大量的 if 或函数指针。类似于:

    1. 获取“function(var1, var2, ..., varN)”形式的字符串
    2. 获取函数的名称(即 '(' ) 之前的所有内容
    3. 获取所有参数(例如strtok()
    4. 识别将常量名称与您的字符串进行比较的函数 (strcmp())
    5. 如果参数是数字(isdigit()sscanf( string, "%d", &amp;parameter ) &gt; 0),则将它们转换为可用的原语(atoi()atof() 等或 sscanf()
    6. 将参数传递给您的函数。

    【讨论】:

    • 谢谢。我认为您的选项 c 对我有帮助。C++ 中有没有办法?
    • @johnkrishna 在任何不支持反射的语言中都无法做到这一点。如果你想这样做,你的类 c 选项是 Java、Objective-C 或 C#。或者你可以自己在 c 或 c++ 中实现反射。
    • @whitlionV 这里函数的参数会不断变化,在这种情况下如何识别类型(因为 strtok() 会将它们都作为字符串给出)
    【解决方案4】:

    如果您想从字符串执行代码(我只是在猜测,您的问题很难理解),那么有很多选择:从将整个 Clang 和 LLVM 嵌入到您的代码中(并确保其JIT 知道您要导出的所有声明)以嵌入简单的脚本语言(如 Lua 或 Guile),并为您要以这种方式调用的所有函数提供包装器。

    【讨论】:

    • 是的,我想执行字符串中的方法。但这是在 C/C++ 中。要正确理解我的问题,请参阅stackoverflow.com/questions/9156389/…
    • 不,您的问题还远未弄清楚。而且,顺便说一句,Clang 是一个 C 编译器。您可能还想尝试嵌入tcc(它是专门为此目的而制作的),它比clang更小更快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多