以下是该方案:
-COM DLL,加载到使用DLL的进程的地址空间中。 - 在DLL内部存在两个全局变量(比如var a,var b)和一个全局函数。 -Process启动,调用全局函数并初始化全局变量a,b并调用CoInitialize(NULL) - 该线程是一个STA。 - 然后相同的全局函数创建STA COM对象
稍后在程序中,同一个线程(上面调用CoInitialize并创建STA COM对象的线程)在此DLL中调用相同的全局C函数(让我们称之为func())。在C函数的范围内,全局变量的状态完全符合预期(即正确初始化)。 函数func()在现有STA COM对象上调用COM方法的那一刻,同一DLL中的COM对象看到完全不同的全局变量副本(var a,var b)。我获取了两个变量的地址,它们在C-func中完全不同,而不是调用COM对象函数。 到底是怎么回事?我认为同一地址空间中的全局变量应该全面可见。
答案 0 :(得分:1)
可能正在加载DLL的两个实例 - 一个由承载DLL的应用程序显式加载,第二个通过CoCreateInstance通过COM子系统加载。前者将查看应用程序进程的DLL搜索路径,而后者将在注册表中查找实现COCLASS的COM组件的位置。
如果你的DLL有一个DllMain(或InitInstance函数,如果它是一个基于MFC的DLL),那么你可以断点它并查看hinstance参数(如果是MFC则查看AfxGetInstanceHandle)以查看是否(a)你初始化两次并且(b)你看到两个不同的DLL实例句柄。如果是这样,那你肯定装了两次。
DLL在文件系统中的位置很重要,因此您应该根据我上面提到的规则查看是否有可能单独加载的不同位置的副本。
通常,永远不应直接加载COM DLL。您应该将您的功能分解为两个DLL,其中COM服务器DLL专用于COM内容。您可以为自己提供一个内部COCLASS接口,如果您愿意,可以将全局变量传递给COM DLL。