【发布时间】:2018-03-29 22:35:08
【问题描述】:
我的系统是带有 Visual Studio 2010 Professional 的 Windows 10 64 位秋季创作者版。
我有一个带有以下 IDL (ISomeInterface.idl) 的 COM 接口:
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(61E246F6-3F22-404B-8EA8-E4D13F3206D6),
pointer_default(unique)
]
interface ISomeInterface : IUnknown
{
HRESULT DoSomething();
}
[
uuid(7EF22D33-5C29-4D32-BFBC-0B276C5F7427),
version(1.0),
helpstring("ISomeInterface 1.0 Type Library")
]
library ISomeInterfaceLib
{
importlib("stdole2.tlb");
[
uuid(BC91D238-B0E1-4FA2-AAC8-195D761DF9DC),
version(1.0),
helpstring("ISomeInterface Class")
]
coclass ISomeInterfaceImpl
{
[default] interface ISomeInterface;
};
};
我用这个命令编译的:
midl /iid "ISomeInterface_i.c" /env win32 /h "ISomeInterface.h" /W1 /char signed /tlb "Release\ISomeInterface.tlb" /Oicf /D "NDEBUG" /robust /nologo /proxy "ISomeInterface_p.c" ISomeInterface.idl
然后我创建一个模块定义文件(ISomeInterface.def):
LIBRARY "ISomeInterface"
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
IID_ISomeInterface DATA
LIBID_ISomeInterfaceLib DATA
然后我使用这些命令构建我的接口 DLL:
cl /c /Zi /W1 /WX- /O2 /Oy- /D WIN32 /D REGISTER_PROXY_DLL /D NDEBUG /D _WINDLL /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\\" /Fd"Release\vc100.pdb" /Gd /TC /analyze- /errorReport:prompt dlldata.c ISomeInterface_i.c ISomeInterface_p.c
link "/OUT:Release\ISomeInterface.dll" rpcns4.lib rpcrt4.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib "/DEF:ISomeInterface.def" /MANIFEST "/ManifestFile:Release\ISomeInterface.dll.intermediate.manifest" "/MANIFESTUAC:level='asInvoker' uiAccess='false'" "/PDB:Release\ISomeInterface.pdb" /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT "/IMPLIB:Release\ISomeInterface.lib" /MACHINE:X86 /DLL Release\dlldata.obj Release\ISomeInterface_i.obj Release\ISomeInterface_p.obj
我的问题是,当我创建我的 ATL 可执行文件时,它总是无法链接给我这个:
SomeApp.obj : error LNK2001: unresolved external symbol _LIBID_ISomeInterfaceLib
我正在使用#include "ISomeInterface.h" 并已将ISomeInterface.lib 添加到链接器->输入。
运行 dumpbin.exe /exports Release\ISomeInterface.dll 提供以下内容:
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file Release\ISomeInterface.dll
File Type: DLL
Section contains the following exports for ISomeInterface.dll
00000000 characteristics
5ABD61A2 time date stamp Thu Mar 29 17:58:58 2018
0.00 version
1 ordinal base
6 number of functions
6 number of names
ordinal hint RVA name
1 0 00001040 DllCanUnloadNow
2 1 00001000 DllGetClassObject
3 2 000010A0 DllRegisterServer
4 3 000010E0 DllUnregisterServer
5 4 000030E8 IID_ISomeInterface
6 5 000030F8 LIBID_ISomeInterfaceLib
Summary
1000 .data
1000 .orpc
1000 .rdata
1000 .reloc
1000 .text
运行dumpbin.exe -headers Release\ISomeInterface.lib | findstr /c:" Symbol name :"显示LIB文件中的符号:
Symbol name : _IID_ISomeInterface
Symbol name : _LIBID_ISomeInterfaceLib
如果我在项目中使用 ISomeInterface_i.c 并删除 LIB,那么它可以正常编译,但我正试图摆脱这种情况......
【问题讨论】:
-
你太努力去锤炼你关于 DLL 应该如何工作的心智模型。 COM 服务器的任何客户端都永远不会链接到您的导入库,因此公开它是没有意义的。不是 COM 的工作方式,他们将使用您的工厂函数 (DllGetClassObject),它是内置在操作系统中的 COM 管道找到它。在运行时发生,从不在链接时发生。传递 guid 的标准工具是
__uuidof运算符和您从library语句中获得的类型库。 -
COM DLL 是我们定义的接口,供多个服务器和客户端同时使用。目前使用它的每个人都必须包含 MIDL 编译器生成的 *_i.c 文件才能链接他们的项目。我希望通过引用 COM DLL 项目生成的导入库来解决这个问题,因为我认为它已经存在了。 ATL 实现服务使用
DECLARE_LIBID(LIBID_ISomeInterfaceLib)语句和调用GetRecordInfoFromGuids(LIBID_ISomeInterface, 1, 0, 0x409, __uuidof(SomeStruct), &pRI)。如果它只是不能那样工作,那么好的。 -
我建议只使用
#import直接从您的.dll(或.tlb)生成客户端代码。 *_i.c 文件实际上是用于 COM 服务器本身,而不是它的客户端。 -
Hans 告诉您,您不需要导出 IID_ISomeInterface 或 LIBID_ISomeInterfaceLib。这些只是常量 - 用户从头文件或注册表中获取它们,具体取决于。
-
生成一个类型库,任何想使用你的对象的人都应该使用
#import