欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 明星 > C++ Dll创建与调用 查看dll函数 MFC 单对话框应用程序(EXE 工程)改为 DLL 工程

C++ Dll创建与调用 查看dll函数 MFC 单对话框应用程序(EXE 工程)改为 DLL 工程

2025/8/22 16:52:11 来源:https://blog.csdn.net/chenhao0568/article/details/147836851  浏览:    关键词:C++ Dll创建与调用 查看dll函数 MFC 单对话框应用程序(EXE 工程)改为 DLL 工程

C++ Dll创建

一、添加 DllMain(必要)

#include <fstream>void Log(const char* msg)
{std::ofstream f("C:\\temp\\dll_log.txt", std::ios::app);f << msg << std::endl;
}BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:Log(">>> DLL_PROCESS_ATTACH");break;case DLL_THREAD_ATTACH:Log(">>> DLL_THREAD_ATTACH");break;case DLL_THREAD_DETACH:Log(">>> DLL_THREAD_DETACH");break;case DLL_PROCESS_DETACH:Log(">>> DLL_PROCESS_DETACH");break;}return TRUE;
}

二、定义导出接口

推荐使用 __declspec(dllexport) 和 extern “C”,不用 .def 文件
推荐你采用的最终写法(只用修饰宏)
// MyDll.h
#pragma once
#define DY __cdecl#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endifextern "C" {MYDLL_API int DY OpenReader();
}

def方式(可选)(不建议用)

在这里插入图片描述

; ReaderF83.def : Declares the module parameters for the DLL.LIBRARY      "ReaderF83.dll"
;DESCRIPTION  'SCPMReader Windows Dynamic Link Library'EXPORTS; Explicit exports can go hereOpenReaderRequestICCCardResetSendAPDUEjectICCCloseReaderGetUID

C++ Dll调用

HMODULE hDll = LoadLibrary("FtSmartPos.dll");
if (hDll)
{{CloseReader pFunc = (CloseReader)GetProcAddress(hDll, "CloseReader");if (pFunc){pFunc(NULL, NULL); // 弹出对话框}else{AfxMessageBox("CloseReader函数未找到");}}FreeLibrary(hDll);
}
else
{AfxMessageBox("FtSmartPos.dll未找到");
}

MFC 单对话框应用程序(EXE 工程)改为 DLL 工程

三步即可。

改为dll

在这里插入图片描述

加dllmain.cpp

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
DWORD start = 0;
BOOL APIENTRY DllMain( HMODULE hModule,long  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH: {logger.INFO_F("#DBG::VDBG:F83 plugin load  VERSION:"+string(VERSION));start = GetTickCount();}break;case DLL_THREAD_ATTACH:logger.INFO_F("#DBG::VREL:F83 plugin unload1 耗时:" + to_string(GetTickCount() - start));break;case DLL_THREAD_DETACH:logger.INFO_F("#DBG::VREL:F83 plugin unload2 耗时:" + to_string(GetTickCount() - start));break;case DLL_PROCESS_DETACH: {logger.INFO_F("#DBG::VREL:F83 plugin unload3 耗时:"+ to_string(GetTickCount()-start));}break;}return TRUE;
}

SCPMReader.cpp

// SCPMReader.cpp : Defines the initialization routines for the DLL.
#include "pch.h"#define EXPORT  __declspec(dllexport)
extern "C" {EXPORT int WINAPIV SendAPDU(HANDLE hCard,	const char* pCmd,	int nCmdLen,	char* pRsp,	int& nRspLen,	const char* pPath)
{return 0;
}
}

两种定义 导致找不到函数名。

#define WINAPI __stdcall
#define WINAPIV __cdecl

改为 extern “C” + __declspec(dllexport) + __cdecl
在这里插入图片描述
在这里插入图片描述

用depandency找不到c语言的,为什么呢?

在这里插入图片描述

用Depandency能看到_GetUID@12

非常好,这个信息 关键


你看到的是:

_GetUID@12

这说明你:

✅ 成功导出了 GetUID 函数
❌ 但它是被 __stdcall 调用约定修饰过的名字


🔥 你的问题的根本原因:

你在 DLL 中写的是:

__declspec(dllexport) int __stdcall GetUID(int a, int b, int c);

那么导出的名字就是:

_GetUID@12

表示:

  • GetUID__stdcall 函数
  • 参数共占 12 字节(3 个 int)

但你在主程序里写:

GetProcAddress(hDll, "GetUID")

这个查找的是未修饰名 "GetUID",当然 找不到


✅ 解决方案:两种选择


✅ 方案一:改为 extern "C" + __declspec(dllexport) + __cdecl

extern "C" __declspec(dllexport)
int __cdecl GetUID(int a, int b, int c);

这样导出的函数名就是 "GetUID",可以直接 GetProcAddress(hDll, "GetUID")

这是一种标准 C 导出方式,推荐用于插件和跨模块 DLL。


✅ 方案二:保持 __stdcall,改用修饰名 "_GetUID@12"

auto pfn = (decltype(&GetUID)) GetProcAddress(hDll, "_GetUID@12");

这当然也能用,但非常不优雅,容易因为参数变更导致名字变掉。


✅ 最佳实践:用头文件 + 宏控制导出名

// DllHeader.h
#ifdef MYDLL_EXPORTS
#define MYAPI extern "C" __declspec(dllexport)
#else
#define MYAPI extern "C" __declspec(dllimport)
#endifMYAPI int __cdecl GetUID(int a, int b, int c);

✅ 验证你的 DLL 导出名

你也可以继续用 dumpbin /exports 查看 DLL 导出名:

dumpbin /exports MyDll.dll

你应该能看到类似:

_GetUID@12

如果你改成了 __cdecl,应该就会看到:

GetUID

是否需要我帮你写一个包含主程序 + DLL 的最小可运行范例?你倾向保留 __stdcall 还是换成 __cdecl

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词