C++ : error LNK2019

本文详细分析了在使用VS2017 Community进行C++项目开发时遇到的LNK2019错误,即无法解析的外部符号_main问题。通过检查项目属性、链接器子系统设置以及确认main函数的存在,最终解决了编译生成错误,为开发者提供了解决类似问题的步骤和思考路径。

IDE环境

VS2017 COMMUNITY

项目属性

发布版本

x86-Debug调试版本-Win32

链接器子系统

控制台(/SUBSYSTEM:CONSOLE)

输出窗口

生成错误
1>---- 已启动生成: 项目: CircleWithConstantMemberFunctions, 配置: Debug Win32 ----
1>MSVCRTD.lib(exe_main.obj) : error LNK2019: 无法解析的外部符号 _main,该符号在函数 “int __cdecl invoke_main(void)” (?invoke_main@@YAHXZ) 中被引用
1>E:\我\C++\C++程序\CircleWithConstantMemberFunctions\Debug\CircleWithConstantMemberFunctions.exe : fatal error LNK1120: 1 个无法解析的外部命令
1>已完成生成项目“CircleWithConstantMemberFunctions.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

尝试操作

对于这个生成错误,我尝试搜索到了一些解释及方法,包括但不限于以下几种:

  1. error LNK2019: 无法解析的外部符号这个错误,“最根本的原因在于链接过程中没有搜索到程序用到的库文件”。

  2. 如果是windows程序(Win32 Application),那么WinMain或者wWinmain是入口函数,在VS2017中新建项目为“win32项目”;
    如果是dos控制台程序(Win32 console Application),那么main或者wMain是入口函数,在VS2017中新建项目为“win32控制台应用程序”。
    若入口函数指定不当,则运行时时找不到配合函数,它就会报告错误。
    解决办法
    1.WINDOWS程序:
    菜单->项目->属性, 配置属性->链接器->系统, 子系统
    子系统的项改为窗口(/SUBSYSTEM:WINDOWS)
    2.CONSOLE程序:
    菜单->项目->属性, 配置属性->链接器->系统, 子系统
    子系统的项改为控制台(/SUBSYSTEM:CONSOLE)
    ——尝试过前两个方法之后,我发现只要是“新建项目”时正确选择了创建控制台程序还是窗体程序,就不必修改这个子系统变量,因为它总是正确的。
    3.“删除**(/subsytem:windows)**开关,让连接程序根据源代码中实现的函数进行正确的操作。”
    ——尝试这个方法时,我的操作是选择“未设置”,我的理解是不初始化入口函数,经编译后,程序提示错误,错误信息为:
    1>LINK : fatal error LNK1561: 必须定义入口点
    故,这个方法我不知道该如何实现。

  3. 新建一个项目,重新编译。
    ——emmmm

  4. 检查类实现文件(.cpp)中是否有main()函数。
    ——检查发现果然没有main函数。我在头文件中完成了类的声明,在类实现文件中完成了类实现,而缺少以下任一操作:
    a.在类实现文件中添加main函数实现代码;
    b.新建一个源文件,将main函数单独列出,从而作为类的目标文件(客户程序)。——我选择将类实现和目标代码分离,故选用了此方法,编译通过,生成成功。

**想来这其实是一个很低级的失误。
**

<think>我们正在解决一个在VS2019中使用静态libusb库时出现的链接错误(LNK2019LNK1120)。这些错误通常是由于链接器无法找到函数定义(比如_libusb_init@4)引起的。根据之前的讨论,我们已经配置了头文件和库路径,但问题仍然存在。现在我们需要深入检查配置并给出解决方案。 关键回顾: 1. 我们使用的是静态库(libusb-1.0.lib)和对应的头文件(libusb.h)。 2. 错误表现为链接阶段无法解析外部符号,说明库没有被正确链接。 解决步骤: 一、检查项目配置 1. **确认包含目录设置正确**: - 在项目属性 -> C/C++ -> 常规 -> 附加包含目录中,设置的头文件目录应该是包含`libusb-1.0`文件夹的目录。例如,如果`libusb.h`位于`include\libusb-1.0\libusb.h`,那么附加包含目录应该设置为`include`(而不是`include\libusb-1.0`)。 2. **确认库目录和库文件**: - 在链接器 -> 常规 -> 附加库目录中,设置库文件(.lib)所在的目录。 - 在链接器 -> 输入 -> 附加依赖项中,添加`libusb-1.0.lib`。 3. **检查平台和配置匹配**: - 确保当前项目的平台(Win32/x64)和配置(Debug/Release)与库文件编译的平台和配置一致。比如,如果库是64位Release版本,那么项目也要设为x64和Release。 4. **设置静态运行时库**: - 对于静态链接的libusb库,我们需要使用静态运行时库。在项目属性 -> C/C++ -> 代码生成 -> 运行时库: - Debug配置:选择`/MTd` - Release配置:选择`/MT` 5. **预处理器定义**: - 在项目属性 -> C/C++ -> 预处理器 -> 预处理器定义中,添加`LIBUSB_STATIC`。这个定义告诉头文件我们正在静态链接libusb。 二、验证库文件 1. **检查库文件是否完整**: - 确认你使用的`libusb-1.0.lib`文件是有效的。可以尝试用dumpbin工具检查库中是否包含所需的符号: ``` dumpbin /symbols libusb-1.0.lib | find "libusb_init" ``` 如果能看到输出,说明库中有这个函数。 2. **确认库的位数**: - 使用32位库链接32位程序,64位库链接64位程序。如果库的位数与目标平台不符,也会导致链接错误。 三、代码示例验证 使用以下简单代码测试: ```c #include "libusb-1.0/libusb.h" #include <stdio.h> int main() { libusb_context *ctx = NULL; int r = libusb_init(&ctx); if (r < 0) { printf("Init error: %d\n", r); return 1; } printf("libusb initialized successfully!\n"); libusb_exit(ctx); return 0; } ``` 四、重新生成解决方案 1. 清理解决方案,然后重新生成。 2. 如果之前生成失败,可能残留中间文件,可以尝试删除解决方案目录下的`.vs`文件夹(需要关闭VS)和项目目录下的`Debug`或`Release`文件夹,然后重新打开VS生成。 五、驱动问题(如果涉及设备操作) 如果需要与设备通信,确保设备驱动已经正确安装(使用libusb-win32或libusbK驱动),但驱动问题通常不会导致编译链接错误,而是运行时错误。 六、其他可能原因 1. **函数调用约定不一致**:如果库是用`__stdcall`调用约定编译的,而我们的代码是`__cdecl`(默认),则会有名称修饰不一致的问题。在错误信息中,我们看到`_libusb_init@4`,这个`@4`表示`stdcall`调用约定(函数名后跟参数总字节数)。如果库是用stdcall编译的,那么我们的代码中应该使用相同的调用约定。但在libusb中,通常是通过头文件中的宏定义的。在静态库中,一般头文件已经处理好了调用约定。因此,我们只需要确保在包含头文件之前定义了`LIBUSB_STATIC`。 2. **库文件损坏**:重新下载或编译libusb静态库。 七、如果以上步骤都无效,可以考虑重新编译libusb静态库。 在Windows上,可以使用MSVC编译libusb静态库: 1. 下载libusb源码(例如从https://github.com/libusb/libusb/releases) 2. 使用CMake生成VS2019项目。 3. 编译静态库(注意选择正确的运行时库选项)。 最后,让我们总结一下常见错误和解决方法: | 错误原因 | 解决方法 | |---------------------------|--------------------------------------------------------------------------| | 附加包含目录错误 | 设置为包含`libusb-1.0`文件夹的目录 | | 附加库目录未设置或错误 | 设置到包含`libusb-1.0.lib`的目录 | | 未添加附加依赖项 | 在附加依赖项中添加`libusb-1.0.lib` | | 运行时库不匹配 | 设置Debug用`/MTd`,Release用`/MT` | | 未定义`LIBUSB_STATIC` | 在预处理器定义中添加`LIBUSB_STATIC` | | 平台不匹配(x86/x64) | 确保项目平台与库的平台一致 | | 库文件损坏 | 重新获取或编译库文件 | 按照以上步骤检查,应该可以解决LNK2019LNK1120错误。 相关问题: 1. 如何检查静态库文件中是否包含特定的函数符号? 2. 在VS2019中如何为不同的配置(Debug/Release)设置不同的库路径? 3. 使用静态库时,为什么需要设置运行时库(/MT、/MTd)? </think>在VS2019中使用静态库libusb时出现LNK2019/LNK1120错误的解决方案如下(请逐步检查配置): ### 一、核心问题诊断 LNK2019表示链接器找不到函数实现(如`_libusb_init`),常见原因: 1. **库文件未正确链接**:`.lib`文件未加入项目 2. **调用约定不匹配**:函数签名不一致(常见于C/C++混合调用) 3. **运行时库冲突**:静态库需匹配`/MT`或`/MTd`[^3] --- ### 二、关键配置步骤 #### 1. 验证静态库配置 | **配置项** | **正确值** | **检查位置** | |--------------------|----------------------------|--------------------------------| | **附加包含目录** | `libusb-1.0`的**父目录** | C/C++ → 常规 → 附加包含目录 | | **附加库目录** | `.lib`文件所在目录 | 链接器 → 常规 → 附加库目录 | | **附加依赖项** | `libusb-1.0.lib` | 链接器 → 输入 → 附加依赖项 | | **预处理器定义** | `LIBUSB_STATIC` | C/C++ → 预处理器 → 预处理器定义 | | **运行时库** | Debug: `/MTd`, Release: `/MT` | C/C++ → 代码生成 → 运行时库 | > 示例路径结构: > ``` > 项目根目录/ > ├── include/ > │ └── libusb-1.0/ ← 附加包含目录指向这里 > │ └── libusb.h > └── lib/ > └── x64/ > └── Release/ > └── libusb-1.0.lib ← 附加库目录指向这里 > ``` #### 2. 检查调用约定(关键!) 在`#include`语句**前**添加调用约定宏: ```c #define LIBUSB_CALL __stdcall // 解决_libusb_init@4错误 #include "libusb-1.0/libusb.h" ``` > 此操作解决名称修饰问题(`libusb_init`→`_libusb_init@4`) #### 3. 验证库文件有效性 使用dumpbin检查符号是否存在: ```powershell dumpbin /symbols libusb-1.0.lib | find "libusb_init" ``` 应有类似输出: ``` 00F 00000000 SECT4 notype () External | _libusb_init ``` --- ### 三、分步解决方案 1. **清理无效缓存**: - 删除项目目录下`.vs`、`x64`、`Debug`等文件夹 - 菜单 → 生成 → 清理解决方案 2. **检查平台匹配**: - 确认项目平台(x86/x64)与库文件编译平台一致 - 通过配置管理器为不同平台设置独立库路径 3. **添加驱动兼容层**(设备通信时必需): ```c #define LIBUSB_OPTION_WEAK_AUTHORITY 1 // 解决权限问题[^2] libusb_set_option(NULL, LIBUSB_OPTION_WEAK_AUTHORITY); ``` 4. **完整测试代码**: ```c #include <stdio.h> #define LIBUSB_STATIC // 启用静态链接 #define LIBUSB_CALL __stdcall // 解决调用约定 #include "libusb-1.0/libusb.h" int main() { libusb_context* ctx = NULL; // 初始化前设置权限选项 libusb_set_option(NULL, LIBUSB_OPTION_WEAK_AUTHORITY); if(libusb_init(&ctx) == LIBUSB_SUCCESS) { printf("libusb initialized!\n"); libusb_exit(ctx); return 0; } return 1; // 失败返回错误 } ``` --- ### 四、错误排查表 | 错误现象 | 解决方案 | |------------------------------|------------------------------| | `LNK2019: _libusb_init@4` | 添加`#define LIBUSB_CALL __stdcall` | | `LNK1120: 无法解析的外部符号` | 检查运行时库是否为`/MT`或`/MTd` | | 运行时设备检测失败 | 安装libusb驱动[^2] | | `C1083: 无法打开libusb.h` | 确认附加包含目录指向父目录 | > 💡 **验证成功标志**:编译后输出窗口显示: > ``` > 1>libusb-1.0.lib(libusb_1.0.obj) : 找到 "_libusb_init" (定义) > 1>程序输出: libusb initialized! > ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值