持续化更新的视状态,在DLL中使用托管扩展
2006-07-20 11:43:22 来源:WEB开发网核心提示: 翻开 C++ 之前几年的日历,一切都是很顺利的,持续化更新的视状态,在DLL中使用托管扩展(6),随着 C++ 的出现,现在的 DLL 有了类,然后调用你的所有静态对象的构造函数,_CRT_INIT 是如何知道调用哪个构造函数的呢?是编译器产生了一个列表,假设你有一个象下面这样的类 Bob
翻开 C++ 之前几年的日历,一切都是很顺利的,随着 C++ 的出现,现在的 DLL 有了类。假设你有一个象下面这样的类 Bobble:
class Bobble {
public:
Bobble() { /* create */ }
~Bobble() { /* destroy */ }
};
假设你的 Bobble DLL 定义了一个全局静态实例:
Bobble MyBobble;
MyBobble 是一个全局对象,所有的函数都可以使用它,就像 MFC 中的 theApp。不知何故,编译器现在必须安排应用程序调用 bobble.dll 中的任何函数之前先调用 Bobble 构造函数。这在 C 语言中是绝不会有的事,在 C 中静态初始化的唯一方法如下:
int GlobalVal=0;
也就是说,将原始数据类型初始化为一个常量值,编译器会进行自身管理。但现在的初始化需要调用运行时执行的函数,而不是在编译时。在 C++ 中,你甚至可以编写下面这样的代码通过某个函数来初始化一个整型:
UINT WM_MYFOOMSG = RegisterWindowMessage("MYFOOMSG");
那么谁来调用这些函数?何时调用?答案是:启动代码(startup code)在调用 DllMain 之前。你也许认为一切都是从 DllMain 开始的,但在此之前,C 运行时 DLL 启动代码调用了你的构造函数。如果你深入 crtdll.c 文件看看 CRT DLL 的初始化序列(这个文件位于\VS.NET\VC7\crt\src目录),你会发现下面的函数:
BOOL WINAPI _DllMainCRTStartup(...) {
if ( /* DLL_PROCESS_ATTACH */ ) {
_CRT_INIT(...); // initialize CRT including ctors
DllMain(...);
}
...
}
我对所发生的重要细节进行了简化:_DllMainCRTStartup 调用另一个 crtdll 函数,_CRT_INIT,然后调用 DllMain。_CRT_INIT 初始化 C 运行时,然后调用你的所有静态对象的构造函数。_CRT_INIT 是如何知道调用哪个构造函数的呢?是编译器产生了一个列表。所以当应用程序调用你的 C++ DLL 时,其加载顺序如下:
更多精彩
赞助商链接