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 ++中的动态源代码[关闭]的主要内容,如果未能解决你的问题,请参考以下文章