C#调用GetProcAddress返回IntPtr.Zero(错误码126)问题排查
问题描述
我有两个项目:一个是作为主程序的C# WinForms项目(基于.NET Framework 4.7.2),另一个是包含导出函数的C++ DLL项目(使用C++17)。
目前遇到的问题:C#程序调用GetProcAddress获取C++ DLL的导出函数时返回IntPtr.Zero,错误码为126(指定模块未找到)。但LoadLibrary并未返回0,说明DLL句柄有效。之前LoadLibrary的问题已经通过将两个项目都编译为x64平台解决了,现在不清楚为什么GetProcAddress会报126错误。
C#项目代码
[DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)] static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName); [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", SetLastError = true)] static extern IntPtr GetProcAddress(int hModule,[MarshalAs(UnmanagedType.LPStr)] string lpProcName); int ModuleHandle = 0; delegate int square_root(int i); square_root FuncSquareRoot; void BeginProgram() { ModuleHandle = LoadLibrary($"{AppDomain.CurrentDomain.BaseDirectory}MyLibrary.dll"); // 当前文件夹路径 if (ModuleHandle == 0) { int last_err = Marshal.GetLastWin32Error(); MessageBox.Show($"LoadLibrary: 错误代码 ({last_err})", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } IntPtr iTemp = GetProcAddress(ModuleHandle, "square_root"); // 使用dllexp.exe查看,这是导出函数的名称... if (iTemp == IntPtr.Zero) { int last_err = Marshal.GetLastWin32Error(); MessageBox.Show($"GetProcAddress: 错误代码 ({last_err})", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } FuncSquareRoot = (square_root)Marshal.GetDelegateForFunctionPointer(iTemp, typeof(square_root)); }
C++ DLL项目代码
MyLibrary.h
#ifdef MYLIB_EXPORTS #define MYLIB_API __declspec(dllexport) #else #define MYLIB_API __declspec(dllimport) #endif MYLIB_API int square_root(int i);
MyLibrary.cpp
#include "pch.h" #include "framework.h" #include "MyLibrary.h" #include <math.h> // 这是一个导出函数示例 MYLIB_API int square_root(int i) { return static_cast<int>(sqrt(static_cast<double>(i))); }
问题分析与解决方案
错误码126虽然字面是“指定模块未找到”,但在GetProcAddress调用时出现,本质是DLL依赖的某个模块加载失败——LoadLibrary仅成功加载了MyLibrary.dll本身,但该DLL依赖的其他系统或第三方库在运行时无法找到,导致后续获取函数地址时触发错误。
具体排查和解决步骤:
- 检查DLL依赖项:使用VS开发命令提示符执行
dumpbin /dependents MyLibrary.dll,查看DLL的所有依赖库,确认这些库都存在于程序运行目录或系统路径中。比如代码用到math.h,可能依赖msvcp140.dll、vcruntime140.dll等VC++运行时库,若缺失就会触发126错误。 - 匹配VC++运行时库:如果C项目用VS编译,确保运行环境安装了对应版本的x64版VC Redistributable;或者在C项目属性中,将“C/C -> 代码生成 -> 运行库”设为
/MT(静态链接运行时库),让DLL打包运行时库,避免外部依赖。 - 确认导出函数名:C++编译器会对函数名进行名字修饰,即便加了
__declspec(dllexport),导出的函数名可能不是square_root,而是类似?square_root@@YAHH@Z的修饰名。执行dumpbin /exports MyLibrary.dll查看实际导出名称,确保GetProcAddress传入的名称完全一致。 - 修正P/Invoke签名:
LoadLibrary的返回类型应为IntPtr(模块句柄是指针类型),当前用int存在类型风险,建议修正:
同时将[DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName); [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);ModuleHandle的类型改为IntPtr,避免类型转换问题。
内容的提问来源于stack exchange,提问作者IOviSpot
相关产品推荐
相关产品推荐

