我的问题如下(都涉及第一种选项):
1. MakeDll.lib具体包含什么? 2. MakeDll.dll何时加载到我的应用程序中,何时卸载?我可以控制吗? 3. 如果我更改MakeDll.dll,是否可以在不重新构建UseDll.exe的情况下使用新版本(前提是界面是旧版本的超集)?特殊情况是当导出多态类并添加新的虚拟函数时。
谢谢。
P.S. 我正在使用MS Visual Studio 2008
它基本上包含DLL中的函数列表,按名称和序数列出(虽然几乎没有人再使用序数)。链接器使用它来在UseDLL.exe中创建一个导入表,即引用(实质上)说:“此文件依赖于MakeDll.dll中的xxx函数”。当加载器加载该可执行文件时,它查看导入表,并(递归地)加载列出的所有DLL,并(至少在概念上)使用GetProcAddress
查找函数,以便将它们的地址放入需要它们的可执行文件中。
通常在加载可执行文件的过程中加载。您可以使用/delayload开关延迟其加载,直到调用来自该DLL的函数。
一般而言是的。具体添加虚拟函数的情况,它将取决于类的vtable布局保持不变,除了新函数被添加之外。除非您采取措施来确保或验证自己,否则依赖它是一个非常糟糕的想法。
// Common.h: interface common to both sides.
// Note: 'extern "C"' disables name mangling on methods.
extern "C" class ISomething
{
// Public virtual methods...
// Object MUST delete itself to ensure memory allocator
// coherence. If linking to different libraries on either
// sides and don't do this, you'll get a hard crash or worse.
// Note: 'const' allows you to make constants and delete
// without a nasty 'const_cast'.
virtual void destroy () const = 0;
};
// MakeDLL.c: interface implementation.
class Something : public ISomething
{
// Overrides + oher stuff...
virtual void destroy () const { delete this; }
};
extern "C" ISomething * create () { return new Something(); }
我已经成功地使用不同的C++编译器在两端部署了这样的设置(即在所有4种可能的组合中交换G++和MSVC)。
你可以随意更改Something
的实现。然而,你不能在没有重新编译两端的情况下更改接口!仔细思考一下,这是相当直观的:双方都依赖于对方对ISomething
的定义。为了增加这种额外的灵活性,你可以使用带编号的接口(如DirectX所做的)或者采用一组接口并测试其功能(如COM所做的)。前者很容易设置但需要纪律,而后者......将会重新发明轮子!