持续化更新的视状态,在DLL中使用托管扩展
2006-07-20 11:43:22 来源:WEB开发网CMyLibInit initlib; // in main app
注意 CMyLibInit 只能适用于某个 exe 使用 DLL 的情况;如果你的客户端是另外一个DLL,你试图想在该DLL的全局范围内实例化 CMyLibInit 的话,在加载器锁定的情况下,__crt_dll_initialize 会被再次调用,从而潜在地触发同样的你正试图避免的 DLL-死锁问题。为了令从另外一个本地 DLL 初始化混合 DLL,你必须找到一个合适的地方来调用混合 DLL 的初始化/终止函数——例如,如果本地DLL是 COM 对象,那么可以在 DllGetClassObject/DllCanUnloadNow 中调用。否则你还需要从本地DLL导出另外一层初始化/终止函数,而本地DLL则调用构造函数或者加载器锁定情况下的 DllMain。
Figure 3 展示了我写的一个使用 CMyLibInit 的 DLL。ManLib 导出一个函数:FormatRunningProcesses,它调用 .NET 框架中的进程类,输出一个以 CString 格式化的运行进程清单,测试程序调用 FormatRunningProcesses 并在消息框中显示此清单,参见 Figure 4:
Figure 4 LibTest
我用 TRACE 诊断机制对 ManLib 进行了跟踪以帮助你了解哪个函数获得调用。Figure 5 是例子程序运行画面,显示了事件顺序。你可以将此输出与 Figure 3 中的 TRACE 输出进行比较以更好地理解调用顺序。如果你自己实现类似 CManLibInit 的机制,记住:在调用 __crt_dll_initialize 之前 (或者在调用 __crt_dll_terminate 之后)不能做任何事情。我刚开始写 ManLib 时,不加思索地将 TRACE 放在最前面,就像下面这样:
CManLibInit::CManLibInit() {
TRACE(...); // Oops!
__crt_dll_initialize();
}
结果我的程序崩溃了,原因是 MFC 的跟踪机制还没有被初始化。而这正是 __crt_dll_initialize 要做的事情。
Figure 5 TraceWin
还有一件事情需要提及。MSDN 库文章中描述的解决方案告诉你在项目设置菜单中将 msycrt.lib 添加到链接库中并将 __DllMainCRTStartup@12(托管名)设置成强制符号引用——“Force Symbol References”。如果你一开始就用使用一个 MFC DLL,便不需要这些步骤,因为 MFC 已经链接你需要的东西。你只要将 /NOENTRY 添加到链接器选项,编写自己的初始化/终止函数并在应用程序中调用它们即可。相关文章参见“Visual C++ 2005 中混合代码的初始化”。
更多精彩
赞助商链接