MFC扩展DLL,函数参数或返回值中有&,调用时报无法解析的外部符号

女神打Boss 2020-11-18 10:16:43
代码如下
#pragma once

#ifndef testMfcDll_H
#define testMfcDll_H


class __declspec(dllexport) testMfcDll;

class testMfcDll
{
public:
testMfcDll(){};
virtual ~testMfcDll(){};
void sayHello();
CString &sayHelloWord();
void sayWhat(CString &);

CString strHello;
};

#endif


// testMfcDll.cpp : 定义 DLL 的初始化例程。
//
#include "stdafx.h"
#include "testMfcDll.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

void testMfcDll::sayHello()
{
//这是win的MessageBox
MessageBox(NULL, _T("hello"), _T("提示"), MB_OK);
}


CString& testMfcDll::sayHelloWord()
{
strHello = _T("hello world");
return strHello;
}


void testMfcDll::sayWhat(CString &str)
{
if(str == _T("hello"))
{
str = _T("get way");
MessageBox(NULL, _T("get way"), _T("提示"), MB_OK);
}else
{
MessageBox(NULL, _T("hello"), _T("提示"), MB_OK);
}
}


调用代码
	testMfcDll test;
test.sayHello();//只调用这个可以正常运行
CString str = _T("hello");
str = test.sayHelloWord();//这个编译不过
test.sayWhat(str);//这个编译不过
MessageBox(str);


错误信息
1>testADODlg.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall testMfcDll::sayWhat(class ATL::CStringT<wchar_t,class StrTraitMFC<wchar_t,class ATL::ChTraitsCRT<wchar_t> > > &)" (?sayWhat@testMfcDll@@QAEXAAV?$CStringT@_WV?$StrTraitMFC@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@@Z),该符号在函数 xxx 中被引用
1>testADODlg.obj : error LNK2019: 无法解析的外部符号 "public: class ATL::CStringT<wchar_t,class StrTraitMFC<wchar_t,class ATL::ChTraitsCRT<wchar_t> > > & __thiscall testMfcDll::sayHelloWord(void)" (?sayHelloWord@testMfcDll@@QAEAAV?$CStringT@_WV?$StrTraitMFC@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@XZ),该符号在函数 xxx中被引用
...全文
459 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
mmcanyu 2020-11-19
  • 打赏
  • 举报
回复
Lib文件没包含进来
Yofoo 2020-11-18
  • 打赏
  • 举报
回复
提示是符号找不到, 如果 sayHello 正常应该整体逻辑是正常的, 应该是部分申明和定义不一致, CString 申明比较复杂, 部分编译器CString 有两套 MFC, 和 ATL, 从上面看exe应该是ATL的, 如果跟dll不一致肯定会有问题 另外CString 比如unicode环境 是CStringW, 其他也可能是CStringA, 在exe,dll如果不一致也会出现符号找不到 另外不同模块之间不推荐使用 CString, 因为不容模块的内存管理是分离的, 交叉使用会出现错误, 推荐用 char*, 或者wchar_t*
女神打Boss 2020-11-18
  • 打赏
  • 举报
回复
引用 1 楼 schlafenhamster 的回复:
strHello = _T("hello world"); strHello 在 哪里 定义 ?
这个是testMfcDll类的成员变量,在.h中有定义
schlafenhamster 2020-11-18
  • 打赏
  • 举报
回复
strHello = _T("hello world"); strHello 在 哪里 定义 ?
zgl7903 2020-11-18
  • 打赏
  • 举报
回复
DLL 接口中 尽量使用基本类型, 不要使用MFC类
女神打Boss 2020-11-18
  • 打赏
  • 举报
回复
接上一楼的问题,创建MFC DLL 项目时的向导中有选择DLL类型,有3种类型,mfc扩展dll, 静态,共享,选择以后就不能在项目属性里面改了 这里的静态 共享 要和exe的静态 共享属性对应,就可以用MFC的东西来封装dll了 但是这里有个问题就是静态和共享dll自带了CWinApp,不知道是啥意思 所以MFC封装dll有2条路,1是上面说的这个 2是把MFC的类型改成char*之类的通用类型 感谢3楼提供思路
女神打Boss 2020-11-18
  • 打赏
  • 举报
回复
引用 3 楼 Yofoo 的回复:
提示是符号找不到, 如果 sayHello 正常应该整体逻辑是正常的, 应该是部分申明和定义不一致, CString 申明比较复杂, 部分编译器CString 有两套 MFC, 和 ATL, 从上面看exe应该是ATL的, 如果跟dll不一致肯定会有问题 另外CString 比如unicode环境 是CStringW, 其他也可能是CStringA, 在exe,dll如果不一致也会出现符号找不到 另外不同模块之间不推荐使用 CString, 因为不容模块的内存管理是分离的, 交叉使用会出现错误, 推荐用 char*, 或者wchar_t*
是你说的这个问题,有个选项,“在共享DLL中使用MFC”exe 和 dll 程序的这个选项要一致就成功了 我是在“在共享DLL中使用MFC”就成功运行了,但是“在静态中使用MFC”编译的dll竟然编译失败,我再找找bug
三:程序的设计: I:设置钩子 设置钩子是通过SetWindowsHookEx ()的API函数. 原形: HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId) idhook:装入钩子的类型. lpfn: 钩子进程的入口地址 hMod: 应用程序的事件句柄 dwThreadId: 装入钩子的线程标示 参数: idHook: 这个参数可以是以下值: WH_CALLWNDPROC、WH_CALLWNDPROCRET、WH_CBT、WH_DEBUG、WH_FOREGROUNDIDLE、WH_GETMESSAGE、WH_JOURNALPLAYBACK、WH_JOURNALRECORD、WH_KEYBOARD、 WH_KEYBOARD_LL、WH_MOUSE、WH_MOUSE_LL、WH_MSGFILTER、WH_SHELL、WH_SYSMSGFILTER。 对于这些参数,我不想一一加以解释,因为MSDN中有关于他们的详细注解。我只挑选其中的几个加以中文说明。 WH_KEYBOARD:一旦有键盘敲打消息(键盘的按下、键盘的弹起),在这个消息被放在应用程序的消息队列前,WINDOWS将会调用你的钩子函数。钩子函数可以 改变和丢弃键盘敲打消息。 WH_MOUSE:每个鼠标消息在被放在应用程序的消息队列前,WINDOWS将会调用你的钩子函数。钩子函数可以改变和丢弃鼠标消息。 WH_GETMESSAGE:每次当你的应用程序调用一个GetMessage()或者一个PeekMessage()为了去从应用程序的消息队列中要求一个消息时,WINDOWS都会调用你的钩子函数。 而钩子函数可以改变和丢弃这个消息。 II:释放钩子 钩子的释放使用的是UnhookWindowsHookEx()函数 原形:BOOL UnhookWindowsHookEx( HHOOK hhk ) UnhookWindowsHookEx()函数将释放的是钩子链中函数SetWindowsHookEx所装入的钩子进程。 hhk: 将要释放的钩子进程的句柄。 III:钩子进程 钩子进程使用函数HookProc;其实HookProc仅仅只是应用程序定义的符号。比如你可以写成KeyBoardHook.但是参数是不变的。Win32 API提供了诸如:CallWndProc、 GetMsgProc、DebugProc、CBTProc、MouseProc、KeyboardProc、MessageProc等函数,对于他们的详细讲解,可以看MSDN我在此只讲解一下KeyBoardHook的含义。 原形:LRESULT CALLBACK KeyBoardHook (int nCode, WPARAM wParam, LPARAM lParam) 说明:钩子进程是一些依附在一个钩子上的一些函数,因此钩子进程只被WINDOWS调用而不被应用程序调用,他们有时就需要作为一个回调函数(CALLBACK)。 参数说明: nCode:钩子代码,钩子进程使用钩子代码去决定是否执行。而钩子代码的值是依靠钩子的种类来定的。每种钩子种类都有他们自己一系列特性的代码。比如对于WH_KEYBOARD, 钩子代码的参数有:HC_ACTION,HC_NOREMOVE。HC_ACTION的意义:参数wParam 和lParam 包含了键盘敲打消息的信息,HC_NOREMOVE的意义:参数wParam 和lParam包含了 键盘敲打消息的信息,并且,键盘敲打消息一直没有从消息队列中删除。(应用程序调用PeekMessage函数,并且设置PM_NOREMOVE标志)。也就是说当nCode等于HC_ACTION时, 钩子进程必须处理消息。而为HC_NOREMOVE时,钩子进程必须传递消息给CallNextHookEx函数,而不能做进一步的处理,而且必须有CallNextHookEx函数的返回值。 wParam:键盘敲打所产生的键盘消息,键盘按键的虚拟代码。 lParam:包含了消息细节。 注意:如果钩子进程中nCode小于零,钩子进程必须返回(return) CallNextHookEx(nCode,wParam,lParam);而钩子进程中的nCode大于零,但是钩子进程并不处理消息, 作者推荐你调用CallNextHookEx并且返回该函数的返回值。否则,如果另一个应用程序也装入WH_KEYBOARD 钩子,那么该钩子将不接受钩子通知并且返回一个不正确的值。 如果钩子进程处理了消息,它可能返回一个非零值去阻止系统传递该信息到其它剩下的钩子或者windows进程。所以最好在钩子进程的最后都返回CallNextHookEx的返回
学习计划:1、每天学习1个小时,大概1个月完成。 2、认真听讲,要自己揣摩,明白原理。 3、动手实践、必须要多做课后练习题,遇到不会的,及时提问。课程目标:从一个纯小白,到真正理解变量的实质,指针的实质,学会C++类及面向对象编程课程简介:敬告:该系列的课程在抓紧录制更新中,敬请大家关注。该系列的课程涉及:FFmpeg,WebRTC,SRS,Nginx,Darwin,Live555,等。包括:音视频、流媒体、直播、Android、视频监控28181、等。---------------------------------------------------  ---------------------------------------------------给学员(从小白到大牛)的3年学习路径及计划技术方面分三块:1.纯开发技术方向2.音视频流媒体专业方向3.项目实战---------------------------------------------------1.纯开发技术方向(1) C++必须要过硬(至少学会10本经典好书)(2) 系统级编程(Windows、Linux),必须特别熟练系统API,灵活运用(3) 框架与工具(Qt、MFC):必须精通其中一种。(4) 架构与设计模式:需要提升一个高度,不再是简单的编码,而是思维模式。(5) 驱动级别(如果有兴趣,可以深入到驱动级:包括Windows、Linux)(6) 最好学习点Java+Html+javascript等WEB技术。2.音视频流媒体专业方向(1) 音视频流媒体基础理论:    必须认真学会,否则看代码就是看天书(2) 编解码方向:精通h.264,h.265(hevc), 包括理论和各个开源库(ffmpeg,libx264,libx265,...)。(3) 直播方向:  精通各种直播协议(rtsp,rtmp,hls,http-flv,...), 钻研各个开源库(live555,darwin,srs,zlmediakit,crtmpserver,...)(4) 视频监控:  理论+开源库(onvif+281818)(EasyMonitor、iSpy、ZoneMinder(web)、...)  3.项目实战(1) Qt项目:  至少要亲手练习10个实战项目(网络服务器、多线程、数据库、图像处理、多人聊天、等等)(2)音视频项目:包括编解码、视频监控、直播等各个方向,都需要亲手实战项目,包括视频服务器、后台管理系统、前端播放器(多端)---------------------------------------------------  具体的内容包括: n 1.全书概览与分析 51.1 初步认识:做到心中有数 51.2 图解:章节关系 61.3 探讨:教学方法论 71.4 探讨:学习方法论 71.5 C++的1.0与2.0 81.6 开发工具Qt5.9和VS2015/7/9 8控制台: 8UI界面: 81.7 安装并搭建Qt5.9.8开发环境 91.下载软件Qt Creator 5.9.8 92.双击开始安装 93.注册Qt账号 114.激活Qt账号 125.选择安装路径 176.选择“安装组件” 197.同意“许可协议” 218.点击“安装”后,请喝杯茶 241.8 捋起袖子开干:几个小案例 35第一:写代码打印“CS”图形 36第二:写代码打印各种图形(作业) 361.9 原书第一章剖析 371.计算机是什么? 372.程序是什么? 383.程序设计 384.C++入门程序示例 40n 第2章 C++基础知识 412.1 变量和赋值 412.2 输入和输出 422.3 数据类型和表达式 432.4 简单控制流程 442.5 程序风格 452.6 x=x-3到底是个什么鬼? 46第3章 更多的控制流程 473.1 使用布尔表达式 473.2 多路分支 483.3 C++循环语句详解 483.4 设计循环 513.5 课堂练习 51第4章 过程抽象和返回值的函数 524.1 自顶向下设计 524.2 预定义函数 534.3 程序员自定义函数 534.4 过程抽象 544.5 作用域和局部变量 554.6 重载函数名称 55第5章 用函数完成所有子任务 565.1 void函数 575.2 传引用参数 575.3 使用过程抽象 595.4 测试和调试函数 595.5 常规调试技术 59第6章 I/O流——对象和类入门 606.1 流和基本文件I/O 606.2 流I/O工具 616.3 字符I/O 62第7章 数组 637.1 数组入门 637.2 函数中的数组 657.3 数组编程 667.4 多维数组 67第8章 字符串和向量 688.1 字符串的数组类型 688.2 标准string类 698.3 向量 71第9章 指针和动态数组 719.1 指针 719.2 手工动态数组 74第10章 定义类 7610.1 结构体 7710.2 类 7810.3 抽象数据类型 8110.4 继承 8210.5 拷贝构造函数 8310.6 析构函数 8410.7 重载赋值(=)操作符 84第11章 友元函数、重载操作符和数组 8611.1 友元函数 8711.2 重载操作符 8811.3 数组和类 9111.4 类和动态数组 91第12章 独立编译和命名空间 9212.1 独立编译 9212.2 命名空间 93第13章 指针和链表 94第14章 递归 95第15章 继承 9615.1 继承基础 9615.2 继承细节 9715.3 多态性(虚函数) 98第16章 异常处理 10016.1 异常处理基础 10016.2 用于异常处理的编程技术 101第17章 模板 10217.1 用于算法抽象的模板 10217.2 用于数据抽象的模板 103第18章 标准模板库(STL) 10418.1 迭代器 10418.2 容器 10518.3 泛型算法 10618.4 不断进化的C++ 106第19章 Qt界面开发入门 106附录 107 

15,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧