WEB开发网
开发学院软件开发VC 持续化更新的视状态,在DLL中使用托管扩展 阅读

持续化更新的视状态,在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 时,其加载顺序如下:

上一页  1 2 3 4 5 6 7 8 9  下一页

Tags:持续化 更新 状态

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接