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

如何复用C#的DllImport定义以适配不同原生DLL?

解决跨DLL调用原生引用计数库的重复定义问题

核心问题分析

你的场景里,my_lib的引用计数基于每个DLL的独立堆管理,必须确保C#模块调用对应DLL的CONSTBUFFER_Create函数,不能混用不同DLL的实例,否则会引发内存泄漏或崩溃。DllImport是编译时绑定属性无法直接重写,但可以通过以下方式避免重复定义函数签名:

解决方案1:抽象基类+派生类复用签名

先定义抽象基类统一声明函数签名,再针对每个DLL创建派生类实现DllImport绑定,仅需写一次签名:

步骤1:定义抽象基类

public abstract class ConstBufferInteropBase
{
    // 统一声明函数签名,无需DllImport
    public abstract IntPtr CONSTBUFFER_Create(byte[] source, uint size);
}

步骤2:为每个DLL创建派生类

每个派生类仅指定对应DLL名称,复用基类签名:

// 对应my_dllA.dll的Interop类
public class ConstBufferInteropA : ConstBufferInteropBase
{
    [DllImport("my_dllA.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern IntPtr CONSTBUFFER_Create(byte[] source, uint size);

    public override IntPtr CONSTBUFFER_Create(byte[] source, uint size)
    {
        return CONSTBUFFER_Create(source, size);
    }
}

// 对应my_dllB.dll的Interop类
public class ConstBufferInteropB : ConstBufferInteropBase
{
    [DllImport("my_dllB.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern IntPtr CONSTBUFFER_Create(byte[] source, uint size);

    public override IntPtr CONSTBUFFER_Create(byte[] source, uint size)
    {
        return CONSTBUFFER_Create(source, size);
    }
}

步骤3:模块中调用

模块A用ConstBufferInteropA,模块B用ConstBufferInteropB,确保调用对应DLL的函数:

// 模块A调用示例
var interopA = new ConstBufferInteropA();
IntPtr bufferHandle = interopA.CONSTBUFFER_Create(new byte[] { 0x01, 0x02 }, 2);

// 模块B调用示例
var interopB = new ConstBufferInteropB();
IntPtr bufferHandleB = interopB.CONSTBUFFER_Create(new byte[] { 0x03, 0x04 }, 2);

解决方案2:部分类拆分签名与绑定

如果函数数量多,可将统一签名放在一个部分类文件,每个DLL的绑定逻辑单独放一个部分类文件:

统一签名的部分类文件

public abstract partial class ConstBufferInterop
{
    public abstract IntPtr CONSTBUFFER_Create(byte[] source, uint size);
    // 其他原生函数签名也可在此统一声明
}

对应my_dllA的部分类文件

public partial class ConstBufferInteropA : ConstBufferInterop
{
    [DllImport("my_dllA.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern IntPtr CONSTBUFFER_Create(byte[] source, uint size);

    public override IntPtr CONSTBUFFER_Create(byte[] source, uint size)
    {
        return CONSTBUFFER_Create(source, size);
    }
}

注意事项

  • 必须严格保证每个C#模块调用对应DLL的Interop类,禁止跨模块混用,否则仍会触发跨DLL引用计数内存问题。
  • CallingConvention需与原生库保持一致(如Cdecl),否则会导致栈损坏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 18:54:58