You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:07:45