C ++中的动态源代码[关闭]

Posted

技术标签:

【中文标题】C ++中的动态源代码[关闭]【英文标题】:Dynamic source code in C++ [closed] 【发布时间】:2010-10-28 01:28:21 【问题描述】:

如何在 C++ 中处理动态源代码?是否可以使用类似 eval("foo") 的东西?

我有一些函数需要根据用户的选择来调用:

     void function1 ();
     void function2 ();
     ...
     void functionN ();

     int main (int argv, char * argv [])
     
         char * myString = new char [100];
         ...
         myString = "1" //user input            
         cout << eval("function"+myString)();
     

通常是怎么做的?

UPD:根据 slacy 和 clinisbut 的回答,我认为我需要创建一个函数注册表。我想它应该作为一个指向函数的指针数组。问题来了,如何声明一个指向函数的指针数组?

【问题讨论】:

我知道您专门询问动态代码 - 但您提出的场景通常使用 switch 语句处理 - 不涉及任何动态。我假设调用哪个函数的选项是有限的。 【参考方案1】:

你的问题的真正答案是这样的:

extern "C" 
void function1 ();
void function2 ();
void function3 ();



 int main (int argv, char * argv [])
 
     char * myString = new char [100];
     ...
     myString = "function1"; //user input     

     void (*f)() = dlsym(RTLD_NEXT, myString);
     f();
 

您可以获取二进制文件中定义的函数(通过其名称,如果它是用 extern "C" 声明的)并调用它。

在 Windows 上,它变得更丑陋,但仍然可能 - 在 GetProcAddress 上阅读

【讨论】:

slsym() 没有返回 void* 吗? C++ 需要 reinterpret_cast 进行该转换。 +1,这实际上是对原始问题的回答。当您只需要设置一个函数指针时,即时编译 C++ 看起来有点矫枉过正。关于 SO 的第一个答案具有不公平的优势...... 第一个答案是我的,但没有那么好,因为我没有弄清楚他到底想要什么。 不,不是。这基本上是所有插件系统的工作原理。【参考方案2】:

C++ 是一种编译语言,因此不存在“eval()”等价物。

对于您提到的具体示例,您可以创建一个函数注册表,将输入(字符串)映射到输出(函数指针),然后调用结果函数。

有几个可用的 C++ 解释器库,虽然性能会很差,但它们可以完成你想要的。谷歌搜索“C++ 解释器”。我已经看到了“Ch”、“CINT”和“clipp”的结果

【讨论】:

但是,您可以动态调用编译器,告诉它生成一个 DLL,加载该 DLL 并拉出并调用您的动态编译函数。我会非常很慢,但你可以做到(假设你的应用程序将在具有可用编译器和链接器的环境中运行)。 如果你想要更快更疯狂的东西,你可以自己在缓冲区中组装机器指令,然后通过函数指针调用缓冲区......虽然这基本上不可能正确地做到,而且会非常特定于平台。 请注意,即使在动态语言上,使用 eval() 也会比正常的解决方案慢得多。 clipp 不是 C++ 解释器,而是一个嵌入框架,可以将其他解释语言与 C++ 代码一起使用。它包括一个 javascript 解释器。【参考方案3】:

如果你真的需要这个,你可以embed a C/C++ interpreter 进入你的程序。不过,您也可以改为embed a more script-like language。

【讨论】:

【参考方案4】:

要回答您通常如何做到这一点的问题,答案是:不是。

必须使用类似eval() 的东西通常是一个设计问题。如果您确实需要它,请嵌入 Lua 或 Python 等脚本语言。

【讨论】:

【参考方案5】:

如果您将 function1 .. functionN 放入 DLL 中,您可以简单地将它们拉出并使用 dlopen/dlsym 按名称调用它们,这可能会让您达到 90% 的目标。

【讨论】:

【参考方案6】:

函数指针呢?

【讨论】:

【参考方案7】:

C++ 语言本身不能直接做到这一点。但是您可以根据用户输入(或其他)使用特定于平台的函数来调用给定 DLL 中的任何函数。例如,在 Windows 上,查找 GetProcAddress() 和 LoadLibrary()

【讨论】:

【参考方案8】:

这是嵌入解释语言(如 LUA)的一个很好的例子。如果您创建与 C++ API 的 LUA 绑定,您将能够通过应用程序中的 LUA 代码动态执行您的代码。

【讨论】:

【参考方案9】:

有两种方法:

    动态加载

    Windows: GetModuleFileName()hModule = NULL 这给出了可执行文件的路径。 使用LoadLibrary(Executable_Name) 将自己加载到内存中。 Linux : 将dloopen()NULL 一起使用,它会将自身加载到内存中。

    在 Windows 和 Linux 中,您都可以定义 void* (function*)() 指针。这始终适用于所有没有参数的签名。这不适用于类方法。

    使用命名空间系统

    这个命名空间很简单,您可以使用Inspect 功能和InvokeMember 方法来动态调用类方法并从类内部访问变量。

【讨论】:

【参考方案10】:

你不能在 C++ 中做到这一点。它是一种强制编译的语言。

无论如何,实现 eval() 所需的许多信息都会在运行时丢失。

【讨论】:

C++ 标准无处禁止通过解释器实现 C++,它可以实现 eval() 样式的函数。函数本身当然是非标准的。 这是不可能的,因为 C++ 中没有反射。您的 eval() 将无法与您的(编译)代码的其余部分进行有效的通信。 C++ 标准中没有任何内容表明 C++ 实现也不支持反射。【参考方案11】:

我会构建一个数组或 STL 列表,其中包含函数指针和您发现的触发对它们的调用的字符串。如果你真的需要调用任意函数,你应该调查 RTTI http://en.wikipedia.org/wiki/Run-time_type_information

【讨论】:

RTTI 将如何帮助识别不是多态类型的函数指针类型? 没错,但我只想提供一个起点。我不相信“为他做功课”比给他一个可以自学的方向更有价值。【参考方案12】:

如何声明指向函数的指针数组?

C 程序员对此问题的回答:

使用 cdecl。

cdecl> 将 functable 声明为指向 函数(int,指向int的指针) 返回双倍

双倍 (*functable)(int , int *)

cdecl> 将 functable 声明为返回 double 的函数 (int) 指针的数组 17

双 (*functable[17])(int )

请注意,函数会自动转换为指向函数的指针,就像数组衰减为指针一样。您不需要 & 来获取函数的地址以将其放入指针中。

如果您使用 C++,使用 std::mapYourFunctionPointerType> 代替数组可能会有所帮助,因为无论如何您都想映射字符串...

OO 方法:

改用多态性。它不会立即解决您的问题,但如果您这样做,很有可能为每个函数设置一个类。

请注意,从根本上说,vtable 是一个指向函数的指针表。

【讨论】:

【参考方案13】:

你想要的是reflection。 C++ 默认不支持它,但是很多人已经为各种目的编写了全面的反射系统。我突然想到的一个是将 C++ 函数绑定到自定义脚本语言。

其他人提到使用 switch 语句(或更准确地说是 if/else 树)。这与可能出现的反射系统一样简单......它可能是您项目的最佳解决方案。 C++ 中的反射是一种相当先进的技术,通常需要大量额外的代码……有时甚至需要自定义预处理器。

还要注意,出于安全目的,eval() 几乎绝不是您想在任何语言中使用的东西。

【讨论】:

【参考方案14】:

在 C++ 应用程序中嵌入和评估代码的最佳方法可能是使用像 python 这样的脚本语言。使用 Boost.Python,“一个 C++ 库,可实现 C++ 和 Python 编程语言之间的无缝互操作性。”

【讨论】:

以上是关于C ++中的动态源代码[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

05.C语言数据常量和变量

C#使用while循环将项添加到List [关闭]

系统中可以关掉的服务都有哪些

将 c/c++ 宏转换为 c# 中的等效代码 [关闭]

C/C++源代码可视化? [关闭]

C:图片中的代码有啥问题? [关闭]