C++跨DLL调用问题:封装求和DLL时编译错误求助
问题分析与解决方案
核心编译错误原因
LVadd = GetProcAddress(DLL18, "sumAB");报错的本质是:LVadd是你定义的普通函数,并非函数指针变量,C++不允许直接给函数名赋值。除此之外,代码还存在函数指针类型不匹配、DLL入口不规范、生命周期管理错误等问题,以下是完整修正方案:
步骤1:修正DLL18的入口函数(规范DLL结构)
DLL的合法入口是DllMain而非main,原代码中的main毫无意义,且sumAB;是无效语句,修正后代码如下:
// dllmain.cpp : Defines the entry point for the DLL application. #include "pch.h" #include "dll18.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } void sumAB(double in1, double in2, double *out1) { *out1 = in1 + in2; }
步骤2:修正DLL19的头文件(修复导出宏错误)
原DLL19头文件误用了dll18_EXPORTS宏,应该替换为自身的导出宏:
#pragma once #ifdef dll19_EXPORTS #define dll19_API __declspec(dllexport) #else #define dll19_API __declspec(dllimport) #endif extern "C" dll19_API void LVadd(double fromLV1, double fromLV2, double* toLV);
步骤3:修正DLL19的主文件(解决编译错误+实现正确调用)
关键修正点:
- 定义与
sumAB完全匹配的函数指针类型 - 用全局变量管理DLL18的模块句柄,避免重复加载/卸载
- 在
LVadd内部调用DLL18的sumAB函数 - 增加错误处理,避免空指针调用崩溃
修正后代码:
// dllmain.cpp : Defines the entry point for the DLL application. #include "pch.h" #include <Windows.h> // 必须包含Windows.h才能使用LoadLibrary等API #include "dll19.h" // 定义匹配sumAB的函数指针:void返回、__cdecl调用约定(extern "C"默认) typedef void(__cdecl *sumABFunc)(double in1, double in2, double* out1); // 全局存储DLL18的模块句柄,进程加载时初始化,退出时释放 HMODULE g_hDLL18 = nullptr; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // 进程加载DLL19时,加载依赖的DLL18 g_hDLL18 = LoadLibraryA("DLL18.dll"); break; case DLL_PROCESS_DETACH: // 进程退出时,释放DLL18 if (g_hDLL18) { FreeLibrary(g_hDLL18); g_hDLL18 = nullptr; } break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; } return TRUE; } void LVadd(double fromLV1, double fromLV2, double* toLV) { // 先判断DLL18是否加载成功 if (!g_hDLL18) { *toLV = 0; // 加载失败时的默认处理 return; } // 获取sumAB函数的地址 sumABFunc sumAB = (sumABFunc)GetProcAddress(g_hDLL18, "sumAB"); if (sumAB) { // 调用DLL18的sumAB完成求和 sumAB(fromLV1, fromLV2, toLV); } else { *toLV = 0; // 获取函数失败时的默认处理 } }
额外说明
- 函数指针的调用约定必须与原函数一致:
extern "C"修饰的函数默认使用__cdecl,如果DLL18的sumAB指定了__stdcall,函数指针也需要同步修改。 - 不要在
DllMain中调用复杂逻辑,这里仅做DLL的加载/释放是安全的。 - 确保DLL18.dll与DLL19.dll在同一目录,或者在系统可搜索的路径中,否则
LoadLibrary会失败。
内容的提问来源于stack exchange,提问作者StackoWhacko
相关产品推荐
相关产品推荐

