MALOUDA-PSA 2025-05-25 12:43 采纳率: 85.6%
浏览 8
已结题

COM组件编译的问题

def:

LIBRARY         Cmpnt.dll
DESCRIPTION     'Chapter 7 Example COM Component (c)1996-1997 Dale E. Rogerson'

EXPORTS
                DllGetClassObject   @2    PRIVATE
                DllCanUnloadNow     @3    PRIVATE
                DllRegisterServer   @4    PRIVATE
                DllUnregisterServer @5    PRIVATE


MAKEFILE:

#
# Chapter 7 - Makefile
#
#
# Flags - Always compiles debug.
#
CPP_FLAGS=/c /MTd /Zi /Od /D_DEBUG
EXE_LINK_FLAGS=/DEBUG
DLL_LINK_FLAGS=/DLL /DEBUG

LIBS=UUID.lib Advapi32.lib Ole32.lib

#################################################
#
# Targets
#
all : client component

client : Client.exe 

component : Cmpnt.dll 
       

#################################################
#
# Shared source files
#

GUIDs.obj : GUIDs.cpp 
    cl $(CPP_FLAGS) GUIDs.cpp

Registry.obj : Registry.cpp Registry.h
    cl $(CPP_FLAGS) Registry.cpp

#################################################
#
# component source files
#

Cmpnt.obj : Cmpnt.cpp Iface.h Registry.h
    cl $(CPP_FLAGS) Cmpnt.cpp


#################################################
#
# Client source files
#

Client.obj : Client.cpp Iface.h 
    cl $(CPP_FLAGS) Client.cpp


#################################################
#
# Link component and automatically register component.
#

Cmpnt.dll : Cmpnt.obj    GUIDs.obj Registry.obj Cmpnt.def 
    link $(DLL_LINK_FLAGS) Cmpnt.obj GUIDs.obj Registry.obj $(LIBS) /DEF:Cmpnt.def 
    regsvr32 -s Cmpnt.dll

#################################################
#
# Link client.
#

Client.exe : Client.obj GUIDs.obj
    link $(EXE_LINK_FLAGS) Client.obj GUIDs.obj $(LIBS)


用 nmake 编译运行没问题, 可是如果用VS2008 编译的话, DLL组件编译可以通过, CLIENT.EXE 编译就抱错:

1>------ 已启动全部重新生成: 项目: CMPNT, 配置: Debug Win32 ------
1>正在删除项目“CMPNT”(配置“Debug|Win32”)的中间文件和输出文件
1>正在编译...
1>CMPNT.CPP
1>REGISTRY.CPP
1>d:\c\com\comclient\compnt\registry.cpp(64) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\string.h(74) : 参见“strcpy”的声明
1>d:\c\com\comclient\compnt\registry.cpp(65) : warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\string.h(79) : 参见“strcat”的声明
1>d:\c\com\comclient\compnt\registry.cpp(105) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\string.h(74) : 参见“strcpy”的声明
1>d:\c\com\comclient\compnt\registry.cpp(106) : warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\string.h(79) : 参见“strcat”的声明
1>d:\c\com\comclient\compnt\registry.cpp(143) : warning C4996: 'wcstombs': This function or variable may be unsafe. Consider using wcstombs_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\stdlib.h(534) : 参见“wcstombs”的声明
1>d:\c\com\comclient\compnt\registry.cpp(202) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\string.h(74) : 参见“strcpy”的声明
1>d:\c\com\comclient\compnt\registry.cpp(207) : warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\string.h(79) : 参见“strcat”的声明
1>d:\c\com\comclient\compnt\registry.cpp(208) : warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\string.h(79) : 参见“strcat”的声明
1>GUIDS.CPP
1>d:\c\com\comclient\compnt\guids.cpp(6) : warning C4005: “INITGUID”: 宏重定义
1>        命令行参数: 参见前面的“INITGUID”定义
1>正在生成代码...
1>正在编译资源清单...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>正在链接...
1>LINK : 没有找到 D:\C\com\COMCLIENT\Debug\CMPNT.dll 或上一个增量链接没有生成它;正在执行完全链接
1>CMPNT.DEF(2) : warning LNK4017: DESCRIPTION 语句不支持目标平台;已忽略
1>CMPNT.DEF : warning LNK4222: 不应为导出符号“DllGetClassObject”分配序号
1>CMPNT.DEF : warning LNK4222: 不应为导出符号“DllCanUnloadNow”分配序号
1>CMPNT.DEF : warning LNK4222: 不应为导出符号“DllRegisterServer”分配序号
1>CMPNT.DEF : warning LNK4222: 不应为导出符号“DllUnregisterServer”分配序号
1>   正在创建库 D:\C\com\COMCLIENT\Debug\CMPNT.lib 和对象 D:\C\com\COMCLIENT\Debug\CMPNT.exp
1>正在嵌入清单...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>生成日志保存在“file://d:\C\com\COMCLIENT\COMPNT\Debug\BuildLog.htm”
1>CMPNT - 0 个错误,14 个警告
2>------ 已启动全部重新生成: 项目: COMCLIENT, 配置: Debug Win32 ------
2>正在删除项目“COMCLIENT”(配置“Debug|Win32”)的中间文件和输出文件
2>正在编译...
2>CLIENT.CPP
2>正在编译资源清单...
2>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
2>Copyright (C) Microsoft Corporation.  All rights reserved.
2>正在链接...
2>CLIENT.obj : error LNK2001: 无法解析的外部符号 _IID_IZ
2>CLIENT.obj : error LNK2001: 无法解析的外部符号 _IID_IY
2>CLIENT.obj : error LNK2001: 无法解析的外部符号 _CLSID_Component1
2>CLIENT.obj : error LNK2001: 无法解析的外部符号 _IID_IX
2>D:\C\com\COMCLIENT\Debug\COMCLIENT.exe : fatal error LNK1120: 4 个无法解析的外部命令
2>生成日志保存在“file://d:\C\com\COMCLIENT\COMCLIENT\Debug\BuildLog.htm”
2>COMCLIENT - 5 个错误,0 个警告
========== 全部重新生成: 成功 1 个,失败 1 个,跳过 0 个 ==========

设置了项目倚赖,问了DEEPSEEK仍然无法解决

  • 写回答

6条回答 默认 最新

  • 一杯年华@编程空间 2025-05-25 12:45
    关注

    一杯年华@编程空间帮您解答,本答案结合 ChatGPT4.0和DeepSeek整理

    我曾经遇到过类似的问题。从你提供的编译日志来看,Client.exe 编译报错是因为找不到 _IID_IZ、_IID_IY、_CLSID_Component1、_IID_IX 这些符号,这通常是由于 GUID 定义未正确包含或链接导致的。下面为你分析并提供解决方案。

    问题分析

    • 错误根源:COM 组件依赖 GUID(接口和类厂的唯一标识),而 Client 项目编译时无法解析这些符号,说明 GUID 的定义或链接路径存在问题。
    • 可能原因
      1. GUIDs.cpp 中定义的 GUID 未正确导出或被 Client 项目引用。
      2. VS 项目配置中缺少 GUID 定义文件的包含路径或链接设置。
      3. 接口头文件(如 Iface.h)中未正确声明 GUID 相关宏(如 DEFINE_GUID)。

    解决方案

    方案一:确保 GUID 定义正确导出并被 Client 项目引用

    1. 检查 GUIDs.cpp
      确认 GUIDs.cpp 中使用 DEFINE_GUID 宏定义了 _IID_IZ、_IID_IY 等接口 GUID 和 _CLSID_Component1 类 GUID,例如:

      // GUIDs.cpp
      #include <objbase.h>
      DEFINE_GUID(IID_IX, 0x12345678, 0x1234, 0x1234, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90);
      DEFINE_GUID(IID_IY, ...); // 其他 GUID 定义
      DEFINE_GUID(CLSID_Component1, ...); // 类 GUID 定义
      

      注意:需包含 objbase.h 头文件,并确保 GUID 值与 IDL 文件(如有)一致。

    2. 将 GUIDs.obj 链接到 Client 项目
      在 VS 项目中,手动将 GUIDs.obj 添加到 Client 项目的链接输入中:

      • 右键 Client 项目 → 属性链接器输入附加依赖项,添加 GUIDs.obj 路径(如 $(SolutionDir)\Debug\GUIDs.obj)。
    3. 头文件包含
      确保 Client.cpp 包含 GUIDs.h(若有)或直接包含 GUIDs.cpp 中的声明(不推荐,但临时可用)。

    方案二:通过头文件共享 GUID 定义(推荐)

    核心思路:将 GUID 定义移至头文件,供组件和客户端共同包含,避免 obj 文件依赖问题。

    1. 创建 GUIDs.h
      在项目中新建 GUIDs.h,内容如下:

      // GUIDs.h
      #pragma once
      #include <objbase.h>
      
      // 接口 GUID
      extern const GUID IID_IX;
      extern const GUID IID_IY;
      extern const GUID IID_IZ;
      
      // 类 GUID
      extern const GUID CLSID_Component1;
      
      // 定义 GUID(在 GUIDs.cpp 中实现)
      #ifdef _COMPONENT_EXPORTS // 避免客户端重复定义
      DEFINE_GUID(IID_IX, 0x12345678, 0x1234, 0x1234, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90);
      // 其他 GUID 定义...
      #endif
      
    2. 修改组件和客户端代码

      • 组件项目(Cmpnt.dll)
        在 Cmpnt.cpp 或 Registry.cpp 中包含 GUIDs.h,并定义 _COMPONENT_EXPORTS 宏(如在编译选项中添加 -D_COMPONENT_EXPORTS),确保 GUID 被实际定义。
      • 客户端项目(Client.exe)
        在 Client.cpp 中包含 GUIDs.h,此时仅引用 extern 声明的 GUID,无需链接 GUIDs.obj。
    3. VS 项目配置

      • 确保 Client 项目包含 GUIDs.h 的路径(右键项目 → 属性C/C++附加包含目录)。
      • 移除 Client 项目中对 GUIDs.obj 的依赖,直接通过头文件引用 GUID。

    最优方案:方案二(头文件共享 GUID 定义)

    优势

    • 解耦组件和客户端的编译依赖,避免手动管理 obj 文件路径。
    • 代码结构更清晰,便于维护和团队协作。
    • 减少编译错误(如方案一中可能因 obj 路径错误导致的链接失败)。

    代码示例

    // Client.cpp(示例)
    #include "GUIDs.h"
    #include <windows.h>
    #include <objbase.h>
    
    int main() {
        CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
        IUnknown* pUnk = nullptr;
        HRESULT hr = CoCreateInstance(
            CLSID_Component1, // 类 GUID
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IUnknown, // 接口 GUID
            reinterpret_cast<void**>(&pUnk)
        );
        // 使用组件...
        pUnk->Release();
        CoUninitialize();
        return 0;
    }
    

    以上方案可解决因 GUID 未正确声明或链接导致的 LNK2001 错误。建议优先尝试方案二,通过头文件共享 GUID 定义,若仍有问题,可检查项目配置中的字符集(如 Unicode/多字节)是否与代码一致,或确认组件 DLL 已正确注册(regsvr32 Cmpnt.dll)。请楼主采纳,如有问题请继续留言。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

问题事件

  • 系统已结题 6月2日
  • 已采纳回答 5月25日
  • 创建了问题 5月25日