棘手的C问题。动态函数调用

时间:2011-03-26 10:02:45

标签: c++ c function dynamic visual-c++

我正在用C / C ++编写一个程序(但c ++类不应该参与),该程序分为两部分。 首先是线程和进程的基本需求。 第二个是用户自定义自己的功能。 模块就像,让我困惑的是用户定制功能。

My Need is as following: 用户可以在给定文件夹中创建新的 *。c 文件,他们可以编写自己的函数。

在他们自己创建函数和编译之后,我可以通过socket或http或argv命令为他们提供一个接口。他们可以唤起他们之前定义的功能。 他们只给我一个像“own_funciton”这样的字符串,然后我调用他们定义的函数。

The question is : how to do this? 

How can i connect the strings and the functions???

我想也许MACRO可能是一个解决方案, 我要求用户定义他们的功能如下: 这只是一个例子

BEGIN_FUNCTION (own_funcion)
{
   //function body
}
END_FUNCTION

HEED :当用户添加新功能时,需要重新编译整个系统。

你可以在MACRO BEGIN_FUNCTION 中做一些事情来存储函数字符串和函数指针。 但我不知道如何专门编写MACRO .. 你有什么建议吗

4 个答案:

答案 0 :(得分:2)

嗯,这对我来说听起来有点像插件架构 - 在这种情况下,这个问题可能对您有所帮助:What's safe for a C++ plug-in system? 我想你需要编写一些通用的插件,你的宏提供了粘合剂以适应用户定义的函数并隐藏复杂的东西。

您还可以查看cppunit(http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page),它基本上可以让您编写一些函数,将它们包装在宏中,这些宏为cppunit框架提供了粘合剂,然后让它们在通用的testrunner中运行。但这听起来不是一件容易的事。使用像lua这样的脚本语言似乎更容易。

更新:有一些c解释器,例如Cint(http://root.cern.ch/drupal/content/cint)。并且公认TCC(http://bellard.org/tcc/)支持解释器样式调用(我猜它是内联编译和执行)。我没有以这种方式使用这些工具,但它们可能会缓解“必须将其编译成动态dll”问题。虽然我仍然希望听到这种理性的理性,而不是像Lua那样使用更适合这些目的的脚本语言。

答案 1 :(得分:2)

这听起来像是关于如何处理动态库加载的与家庭作业相关的问题,这就是大多数插件系统的构建方式。了解如何在平台中实现动态库加载。

举个例子,在linux中,你会看到dlopen / dlclose / dlsym个函数。基本上用户实现了一个.so对象,当你的应用程序加载时,它会打开带有.so的{​​{1}}文件,一旦加载了库,并且用户输入了一个字符串,你就可以看了对于具有dlopen的特定函数名称,并通过函数指针调用它。完成库后,使用dlsym发布它。

有些库可以帮助我们,例如Boost.Extension,它为底层操作系统调用提供了一个多平台接口。

答案 2 :(得分:1)

你有很多选择

1)如果你的函数很小,你可以创建一个宏来简单地声明一个函数,并将函数添加到指向你的类型函数的指针映射(typedef your function)

int FunctionName()
{
   //user code
}
map["FunctionName"] = FunctionName;

执行此操作的宏不难写

当你想要执行时,只需从map中选择函数函数并调用它

2)你的功能越大你必须考虑一个插件系统。导出函数的Dll。在“服务器”上,您可以枚举并加载这些dll并执行所请求的功能

3)一个很好的版本,使用脚本引擎,允许用户在服务器上执行scrips。您可以使用IActiveScript或许多可用的免费脚本引擎之一来实现此目的。

修改

4)我想到了另外一种可能性。

  • 将.c文件添加到dll项目中。
  • 将__declspec(dllexport)修饰符添加到您要添加的每个函数中(最终通过宏)
  • Enum导出这样的功能
void EnumDllFunctions()
{
    BYTE *hMod = (BYTE*)GetModuleHandle("KERNEL32.DLL");
    IMAGE_NT_HEADERS *pnt = (IMAGE_NT_HEADERS*)&hMod[PIMAGE_DOS_HEADER(hMod)->e_lfanew];
    IMAGE_EXPORT_DIRECTORY *exp = (IMAGE_EXPORT_DIRECTORY*)&hMod[pnt->OptionalHeader.DataDirectory->VirtualAddress];
    DWORD *dwFunctions = (DWORD*)&hMod[exp->AddressOfNames];
   for (DWORD ctr = 0; ctr < exp->NumberOfNames; ctr++) 
   {
       printf("%s\n", (char*)&hMod[dwFunctions[ctr]]);
   }

答案 3 :(得分:0)

听起来像是在寻找外部函数接口,例如libffi