1>E1400Dlg.obj : error LNK2019: 无法解析的外部符号 __imp__Demo@12,该符号在函数 "protected: v

本文解决了一个关于VC2010 MFC项目中无法解析外部符号的问题,涉及DLL引入步骤及注意事项,提供了详细的配置指导。
编译器:vc2010 mfc 引入库问题
 
问题描述:
 
1>E1400Dlg.obj : error LNK2019: 无法解析的外部符号  __imp__Demo@12,该符号在函数 "protected: virtual int __thiscall CE1400Dlg::OnInitDialog(void)" ( ?   OnInitDialog@CE1400Dlg@@MAEHXZ) 中被引用

1>C:\Documents and Settings\ylxk\桌面\E1400\Debug\E1400.exe : fatal error LNK1120: 1 个无法解析的外部命令
 
解决方法:
1、引入库没有正确加入
2、需要 #define GLUT_DISABLE_ATEXIT_HACK
 
dll 的引入:
1、项目->项目属性->配置属性->链接器->常规->附加库目录     此处添加需要加入库的文件目录
2、项目->项目属性->配置属性->链接器->输入->附加依赖项    此处添加引入库,或者引入库的绝对路径
 
有效帮助:
<think>我们有两个主要问题需要解决: 1. 之前代码中`m_bRunning`和`WM_UDP_RECV`未声明的问题(已经在上一次回答中给出解决方案,但用户可能还需要整合) 2. 当前`CMyTcpSocket`类的`OnConnect`和`OnClose`函数出现“无法解析外部符号”错误(LNK2001) 问题分析: 1. `m_bRunning`和`WM_UDP_RECV`未声明:需要按照之前的方案在适当位置声明。 2. `OnConnect`和`OnClose`的LNK2001错误:通常是因为在类声明中声明了这些虚函数,但没有提供实现(或者实现不正确)。 解决步骤: 一、解决`m_bRunning`和`WM_UDP_RECV`未声明的问题(重复上一次回答的要点,但更简洁): 1. 在对话框类头文件中声明`m_bRunning`(例如`CMFCApplication1Dlg.h`): ```cpp class CMFCApplication1Dlg : public CDialog { // ... 其他代码 public: bool m_bRunning; // 线程控制变量 // ... }; ``` 并在构造函数中初始化:`m_bRunning(false)` 2. 定义自定义消息`WM_UDP_RECV`(通常在`stdafx.h`或资源文件中定义): ```cpp #define WM_UDP_RECV (WM_USER + 100) ``` 3. 在对话框类中添加消息映射和消息处理函数: 在头文件中声明消息处理函数: ```cpp afx_msg LRESULT OnUdpRecv(WPARAM wParam, LPARAM lParam); ``` 在实现文件中添加消息映射: ```cpp BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialog) // ... 其他消息映射 ON_MESSAGE(WM_UDP_RECV, &CMFCApplication1Dlg::OnUdpRecv) END_MESSAGE_MAP() ``` 然后实现`OnUdpRecv`函数。 二、解决`CMyTcpSocket`类的`OnConnect`和`OnClose`函数无法解析外部符号错误(LNK2001): 原因:`CMyTcpSocket`类是从`CAsyncSocket`(或`CSocket`)派生的,我们重写了虚函数(如`OnConnect`, `OnClose`),但可能没有提供实现,或者实现不正确。 步骤: 1. 在`CMyTcpSocket`类的头文件中声明这些函数为`override`(或确保声明为虚函数): ```cpp class CMyTcpSocket : public CAsyncSocket { public: virtual void OnConnect(int nErrorCode); // 连接事件 virtual void OnClose(int nErrorCode); // 关闭事件 // ... 其他函数 }; ``` 2. 在对应的cpp文件中提供这两个函数的实现: ```cpp void CMyTcpSocket::OnConnect(int nErrorCode) { if (nErrorCode == 0) { // 连接成功 } else { // 连接失败 } // 注意:如果需要,调用基类的实现 CAsyncSocket::OnConnect(nErrorCode); } void CMyTcpSocket::OnClose(int nErrorCode) { // 处理关闭事件 CAsyncSocket::OnClose(nErrorCode); } ``` 3. 如果已经实现了这两个函数,检查是否在类声明中声明了但没有在cpp文件中实现,或者函数签名不一致(如参数类型、函数名拼写错误等)。 三、其他注意事项: 1. 确保在项目设置中链接了必要的库,如`ws2_32.lib`(在项目属性->链接器->输入->附加依赖项中添加)。 2. 在`stdafx.h`中包含必要的头文件,如`afxsock.h`(用于MFC socket支持)。 示例代码结构: CMyTcpSocket.h: ```cpp #pragma once #include <afxsock.h> class CMyTcpSocket : public CAsyncSocket { public: virtual void OnConnect(int nErrorCode); virtual void OnClose(int nErrorCode); // ... 其他自定义函数和变量 }; ``` CMyTcpSocket.cpp: ```cpp #include "pch.h" #include "CMyTcpSocket.h" void CMyTcpSocket::OnConnect(int nErrorCode) { // 实现代码 CAsyncSocket::OnConnect(nErrorCode); // 可选:调用基类 } void CMyTcpSocket::OnClose(int nErrorCode) { // 实现代码 CAsyncSocket::OnClose(nErrorCode); // 可选:调用基类 } ``` 四、关于线程函数的修正: 之前的线程函数是静态成员函数,因此不能直接访问非静态成员`m_bRunning`。解决方法: 1. 在创建线程时将`this`指针传递给线程函数(使用`AfxBeginThread`或`std::thread`时传入`this`)。 2. 在线程函数中通过参数获取对话框对象指针。 修改后的线程函数示例(使用MFC的`AfxBeginThread`): 在对话框类中声明线程函数为静态: ```cpp static UINT UdpRecvThread(LPVOID pParam); ``` 启动线程的地方: ```cpp m_bRunning = true; AfxBeginThread(UdpRecvThread, this); // 将this作为参数传入 ``` 修改线程函数: ```cpp UINT CMFCApplication1Dlg::UdpRecvThread(LPVOID pParam) { CMFCApplication1Dlg* pDlg = (CMFCApplication1Dlg*)pParam; // 使用pDlg->m_bRunning while (pDlg->m_bRunning) { // ... 接收数据 ::PostMessage(pDlg->m_hWnd, WM_UDP_RECV, 0, (LPARAM)new CString(buffer, len)); } return 0; } ``` 总结: 1. 声明和定义自定义消息`WM_UDP_RECV`和成员变量`m_bRunning`。 2. 为`CMyTcpSocket`类的虚函数`OnConnect`和`OnClose`提供实现。 3. 修正线程函数以访问对话框成员。 相关问题: 1. 如何在MFC中正确创建和使用自定义消息? 2. MFC中如何安全地停止工作线程? 3. 如何正确重写`CAsyncSocket`类的虚函数? 4. 如何处理socket连接失败的情况? </think>### 解决 MFC 代码中未声明符号和链接错误问题 #### **一、解决 `m_bRunning` 和 `WM_UDP_RECV` 未声明问题** 1. **声明线程控制变量** 在对话框类头文件中添加: ```cpp // CMFCApplication1Dlg.h class CMFCApplication1Dlg : public CDialog { public: volatile BOOL m_bRunning; // 线程控制标志 }; ``` 在构造函数中初始化: ```cpp CMFCApplication1Dlg::CMFCApplication1Dlg(CWnd* pParent) : m_bRunning(FALSE) {} // 初始化为未运行 ``` 2. **定义自定义消息** 在 `stdafx.h` 中添加: ```cpp #define WM_UDP_RECV (WM_USER + 0x100) // 保留偏移量≥100 ``` 3. **添加消息处理函数** ```cpp // CMFCApplication1Dlg.h afx_msg LRESULT OnUdpRecv(WPARAM wParam, LPARAM lParam); // CMFCApplication1Dlg.cpp BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialog) ON_MESSAGE(WM_UDP_RECV, &OnUdpRecv) END_MESSAGE_MAP() LRESULT CMFCApplication1Dlg::OnUdpRecv(WPARAM, LPARAM lParam) { CString* pData = reinterpret_cast<CString*>(lParam); // 处理数据... delete pData; // 释放内存 return 0; } ``` --- #### **二、解决 `CMyTcpSocket` 链接错误 (LNK2001)** 错误原因:声明了虚函数但未实现。解决方案: 1. **在派生类中实现虚函数** ```cpp // CMyTcpSocket.h class CMyTcpSocket : public CAsyncSocket { public: virtual void OnConnect(int nErrorCode); // 必须覆盖实现 virtual void OnClose(int nErrorCode); // 必须覆盖实现 }; // CMyTcpSocket.cpp void CMyTcpSocket::OnConnect(int nErrorCode) { if (nErrorCode == 0) { // 连接成功处理 } else { // 错误处理 (nErrorCode 包含错误码) } CAsyncSocket::OnConnect(nErrorCode); // 调用基类实现 } void CMyTcpSocket::OnClose(int nErrorCode) { // 清理资源 CAsyncSocket::OnClose(nErrorCode); // 调用基类实现 } ``` 2. **检查项目配置** - 确保 `CMyTcpSocket.cpp` 包含在项目编译中 - 在项目属性中添加库依赖: `项目属性 → 链接器 → 输入 → ws2_32.lib` --- #### **三、完整 UDP 线程修改方案** ```cpp UINT CMFCApplication1Dlg::UdpRecvThread(LPVOID pParam) { CMFCApplication1Dlg* pThis = reinterpret_cast<CMFCApplication1Dlg*>(pParam); SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); sockaddr_in addr = { AF_INET, htons(6000) }; bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)); char buffer[1024]; while (pThis->m_bRunning) { int len = recv(sock, buffer, sizeof(buffer), 0); if (len > 0 && ::IsWindow(pThis->m_hWnd)) { ::PostMessage(pThis->m_hWnd, WM_UDP_RECV, 0, reinterpret_cast<LPARAM>(new CString(buffer, len))); } } closesocket(sock); return 0; } ``` > 启动线程时传递 `this` 指针: > `AfxBeginThread(UdpRecvThread, this);` --- ### **关键注意事项** 1. **线程安全** - 共享变量 `m_bRunning` 使用 `volatile` 声明 - 跨线程数据传递使用 `PostMessage` 避免竞态条件[^1] 2. **资源管理** - 动态分配的 `CString` 必须在消息处理函数中释放 - Socket 关闭时检查有效句柄:`if (sock != INVALID_SOCKET)` 3. **虚函数覆盖** - MFC 的 `OnConnect/OnClose` 是虚函数,必须实现派生类版本 - 错误处理时检查 `nErrorCode` 参数 --- ### **相关问题** 1. 如何诊断和处理 Winsock 错误代码? 2. MFC 中如何正确实现多线程数据传递? 3.函数覆盖失败还有哪些常见原因? 4. 如何优化 UDP 接收线程的性能? [^1]: MSDN - MFC 多线程编程指南
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值