Sooooo我正在写一个脚本解释器。基本上,我想要一些存储在DLL中的类和函数,但我希望DLL在链接到它的程序中查找函数,例如,
program dll
----------------------------------------------------
send code to dll-----> parse code
|
v
code contains a function,
that isn't contained in the DLL
|
list of functions in <------/
program
|
v
corresponding function,
user-defined in the
program--process the
passed argument here
|
\--------------> return value sent back
to the parsing function
我基本上想知道,如何用gcc编译DLL?好吧,我正在使用gcc的windows端口。一旦我编译了包含我的类和函数的.dll,我如何用我的程序链接到它?如何使用DLL中的类和函数? DLL可以从链接到它的程序调用函数吗?如果我创建一个类{...}对象;在DLL中,然后当程序加载DLL时,对象是否可用于程序?在此之前,我真的需要知道在继续这个项目之前如何在C ++中使用DLL。
“你能否添加更多关于你希望DLL在主程序中调用函数的细节?”
我认为该图解释了它...使用DLL的程序将一段代码传递给DLL,它解析代码,如果在所述代码中找到函数调用,则调用DLL中的相应函数...例如,如果我传递“a = sqrt(100)”,那么DLL解析器函数将找到对sqrt()的函数调用,并且在DLL中将是相应的sqrt()函数,它将计算平方根传递给它的参数,然后它将获取该函数的返回值并将其放入变量a ...就像任何其他程序一样,但是如果找不到sqrt()函数的相应处理程序DLL(会有一个本机支持的函数列表)然后它将调用一个类似的函数,该函数将驻留在程序中使用DLL来查看该名称是否有任何用户定义的函数。
因此,假设您将DLL加载到程序中,使您的程序能够解释此特定语言的脚本,程序可以调用DLL来处理单行代码或将脚本的文件名交给处理......但是如果你想在脚本中添加一个符合你程序目的的命令,你可以说在DLL中设置一个布尔值,告诉你要在其语言中添加函数,然后在你的代码中创建一个函数列出你正在添加的函数(DLL会用它想要的函数名称来调用它,如果该函数是你的代码中包含的用户定义函数,该函数将使用DLL传递给它的参数调用相应的函数,将用户定义函数的返回值返回给DLL,如果它不存在,则返回错误代码或NULL或其他内容)。我开始看到我必须找到另一种方法来使函数调用只有一种方式
答案 0 :(得分:8)
This link解释了如何以基本方式完成。
在大图中,当你创建一个dll时,你正在创建一个在运行时加载的库。它包含许多导出的符号。这些符号通常是对方法或函数的引用,加上编译器/链接器goo。
当你正常构建一个静态库时,只有最少的goo,链接器会提取它所需的代码并在你的可执行文件中为你重新打包它。
在一个dll中,你实际上得到了两个最终产品(三个真正 - 只是等待):一个dll和一个存根库。存根是一个静态库,看起来与常规静态库完全相同,除了不是执行代码,每个存根通常是对常规例程的跳转指令。常用例程加载你的dll,获取你想要调用的例程的地址,然后修补原始的跳转指令去那里,所以当你再次调用它时,你最终会进入你的dll。
第三个最终产品通常是一个头文件,它会告诉您库中数据类型的所有信息。
所以你的步骤是:创建你的头文件和代码,构建一个dll,从头文件/代码/一些导出函数列表中构建一个存根库。结束代码将链接到存根库,它将加载dll并修复跳转表。
编译器/链接器goo包括确保运行时库在需要的地方,确保执行静态构造函数,确保静态析构函数注册以供以后执行等等。
现在您的主要问题是:如何在dll中编写可扩展代码?有许多可能的方法 - 一种典型的方法是定义一个纯抽象类(也就是接口)来定义一个行为,并将其传递给一个处理例程,或者创建一个例程来注册接口来做工作,然后处理例程要求注册商提供一个对象来处理它的工作。
答案 1 :(得分:2)
关于你打算解决的问题的细节,也许你应该看一下像lua这样的可扩展解析器而不是构建你自己的解析器。
更具体的焦点。
DLL(通常是?)意味着它本身就是完整的,或者明确地知道用什么来完成它自己。
我的意思是,你不能有一个调用应用程序隐式提供的方法来完成DLL的功能。
然而,您可以通过调用应用程序为您的API提供方法,从而使DLL完全包含并明确传递知识。
如何使用DLL中的类和函数?
在代码中包含标题,当链接模块(exe或其他dll)时,会检查dll的完整性。
DLL可以从链接到它的程序中调用函数吗?
是的,但必须在运行时告诉他们。
如果我创建一个类{...}对象;在DLL中,然后当程序加载DLL时,对象是否可用于程序?
是的,它将可用,但是您需要注意一些限制。例如在内存管理方面,重要的是:
实例!
这是将函数传递给dll的基本思路,但在您的情况下可能不是最有用的,因为您需要预先知道您想要提供的其他函数。
// parser.h
struct functions {
void *fred (int );
};
parse( string, functions );
// program.cpp
parse( "a = sqrt(); fred(a);", functions );
您需要的是一种注册函数的方法(以及它们与dll的详细信息。) 这里更大的问题是细节位。但是跳过那些你可能会像wxWidgets那样做类注册。当您的应用程序构造method_fred时,它将调用构造函数并通过使用off methodInfo注册dll。解析器可以查找methodInfo以获取可用的方法。
// parser.h
class method_base { };
class methodInfo {
static void register(factory);
static map<string,factory> m_methods;
}
// program.cpp
class method_fred : public method_base {
static method* factory(string args);
static methodInfo _methoinfo;
}
methodInfo method_fred::_methoinfo("fred",method_fred::factory);
答案 2 :(得分:0)
这听起来像是数据结构的工作。
创建一个包含关键字和与每个关键字相关联的函数的结构。
struct keyword {
const char *keyword;
int (*f)(int arg);
};
struct keyword keywords[max_keywords] = {
"db_connect", &db_connect,
}
然后在DLL中编写一个函数,将该数组的地址传递给:
plugin_register(keywords);
然后在DLL内部可以执行:
keywords[0].f = &plugin_db_connect;
使用此方法,处理脚本关键字的代码保留在主程序中,而DLL操纵数据结构以获取其自己的函数。
将它带到C ++,使结构成为一个类,而不是包含std :: vector或std :: map或其他任何关键字和一些操作它们的函数。
答案 3 :(得分:0)
Winrawr,在你继续之前,首先阅读:
Any improvements on the GCC/Windows DLLs/C++ STL front?
基本上,在你的DLL周围传递STL字符串时可能会遇到问题,而且你也可能遇到跨越DLL边界的异常问题,虽然这不是我经历过的事情。 / p>
答案 4 :(得分:-1)
您始终可以使用load library
在运行时加载dll