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

C#调用含嵌套结构体指针的C/C++ DLL时函数指针映射失败问题

解决C#调用C DLL函数指针映射为null的问题

我来帮你排查下问题所在,你的代码里有几个关键错误导致函数指针始终无法正确映射:


1. 委托签名与C函数不匹配

你定义的委托参数和C DLL里的函数签名完全不符,这会导致CLR无法正确绑定函数指针:

  • C里的Close是无参数函数,但你给FP_DLL_TEST_CLOSE加了ref VersionInfo参数
  • C里的RegisterClient接收int id参数,但你给FP_DLL_TEST_RC加了ref VersionInfo参数

2. 错误的内存分配逻辑

你提前手动分配了内存并赋值给dllTest.psItf,但实际上DLL的GetDllTestFP函数是要将自身内部的结构体指针赋值给传入的psFP->psItf,不需要你提前分配内存。

3. 未正确将指针转换为C#结构体

调用GetDllTestFP后,你没有把dllTest.psItf指向的非托管结构体转换为C#的DllTestFPStruct实例,直接使用了之前创建的空结构体,自然所有委托都是null。


修正后的完整C#代码

using System;
using System.Runtime.InteropServices;

class Program
{
    // 先定义和C结构体匹配的VersionInfo
    [StructLayout(LayoutKind.Sequential)]
    public struct VersionInfo
    {
        public uint uMajor;
        public uint uMinor;
        public uint uMRevision;
    }

    // 修正委托签名,完全匹配C函数
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int FP_DLL_TEST_CLOSE();

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int FP_DLL_TEST_INIT(ref VersionInfo sVersInfo);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int FP_DLL_TEST_RC(int id);

    [StructLayout(LayoutKind.Sequential)]
    public struct DllTestFPStruct
    {
        public FP_DLL_TEST_CLOSE Close;
        public FP_DLL_TEST_INIT Init;
        public FP_DLL_TEST_RC RegisterClient;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DllTestMgr
    {
        public IntPtr psItf;
        public int iDummy;
    }

    [DllImport("DllTestC.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetDllTestFP(ref DllTestMgr ps);

    static void Main(string[] args)
    {
        DllTestMgr dllTest = new DllTestMgr();
        // 不需要提前分配内存,直接传入空的Mgr实例
        GetDllTestFP(ref dllTest);

        if (dllTest.psItf == IntPtr.Zero)
        {
            Console.WriteLine("Failed to get DLL function pointers!");
            return;
        }

        // 将非托管指针转换为C#结构体
        DllTestFPStruct dllFPs = Marshal.PtrToStructure<DllTestFPStruct>(dllTest.psItf);

        // 测试调用函数
        VersionInfo vInfo = new VersionInfo { uMajor = 1, uMinor = 0, uMRevision = 0 };
        dllFPs.Init(ref vInfo);
        dllFPs.RegisterClient(123);
        dllFPs.Close();
    }
}

额外注意事项

  • 确保你的DLL是和C#程序同架构编译的(比如x86对应x86,x64对应x64),否则会出现调用失败或者指针错误
  • C DLL里的静态函数Close、Init、RegisterClient没有返回值,但声明的是int类型,最好补充返回值(比如return 0;),避免未定义行为

内容的提问来源于stack exchange,提问作者arash javanmard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:31:58