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

如何在其他项目引用C#类库时自动关联依赖的C++ DLL?

解决C#类库引用C++ DLL后,下游项目无需手动复制DLL的方法

针对你遇到的问题——引用封装了C++ DLL的C#类库时,下游项目找不到A_Cpp.dll的情况,以下是几种无需手动复制的解决方案:

方案一:将C++ DLL嵌入C#类库,运行时自动释放

  1. 在UsingCppDllProject项目中,选中Ref_Cpp/A_Cpp.dll,右键设置属性:
    • 生成操作:嵌入的资源
    • 复制到输出目录:不复制
  2. 修改MyPortingClass,添加静态构造函数,在类首次加载时将嵌入的DLL释放到可访问路径:
namespace UsingCppDllProject
{
    public class MyPortingClass
    {
        private static string _dllPath;
        private delegate int AddNumberDelegate(int firstNum, int secondNum);
        private static AddNumberDelegate _addNumberFunc;

        static MyPortingClass()
        {
            // 拼接嵌入资源的完整名称(命名空间+目录+文件名)
            string resourceName = "UsingCppDllProject.Ref_Cpp.A_Cpp.dll";
            // 获取C#类库所在目录
            string assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            _dllPath = Path.Combine(assemblyDir, "Ref_Cpp", "A_Cpp.dll");

            // 创建目标目录并释放DLL文件
            Directory.CreateDirectory(Path.GetDirectoryName(_dllPath));
            using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
            {
                using (FileStream fileStream = new FileStream(_dllPath, FileMode.Create))
                {
                    resourceStream.CopyTo(fileStream);
                }
            }

            // 动态加载DLL并绑定函数
            IntPtr dllHandle = LoadLibrary(_dllPath);
            if (dllHandle == IntPtr.Zero)
            {
                throw new System.ComponentModel.Win32Exception();
            }

            IntPtr funcPtr = GetProcAddress(dllHandle, "AddNumber");
            if (funcPtr == IntPtr.Zero)
            {
                throw new System.ComponentModel.Win32Exception();
            }

            _addNumberFunc = Marshal.GetDelegateForFunctionPointer<AddNumberDelegate>(funcPtr);
        }

        public int Do_AddFunction(int num1, int num2)
        {
            return _addNumberFunc(num1, num2);
        }

        [DllImport("kernel32.dll")]
        private static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
    }
}

这种方式会在类首次被调用时自动释放C++ DLL到类库所在目录,下游项目引用类库后无需额外操作。

方案二:通过生成事件自动复制C++ DLL,下游项目自动同步

  1. 在UsingCppDllProject项目属性的「生成事件」标签中,在「后期生成事件命令行」添加:
xcopy "$(ProjectDir)Ref_Cpp\A_Cpp.dll" "$(OutputDir)Ref_Cpp\" /Y /I

该命令会在类库编译完成后,自动将Ref_Cpp下的A_Cpp.dll复制到类库输出目录(Release/Debug)的Ref_Cpp子目录中。
2. 下游项目引用UsingCppDllProject时,确保引用的「复制本地」属性为True(默认值),这样类库输出目录下的所有文件(包括Ref_Cpp/A_Cpp.dll)会自动同步到下游项目的输出目录,DllImport的相对路径就能正确定位到文件。

方案三:动态构造DLL路径并加载

放弃固定的DllImport字符串,通过程序集目录动态获取C++ DLL路径,使用系统API加载DLL并绑定函数:

namespace UsingCppDllProject
{
    public class MyPortingClass
    {
        private delegate int AddNumberDelegate(int firstNum, int secondNum);
        private AddNumberDelegate _addNumberFunc;

        public MyPortingClass()
        {
            // 获取C#类库所在目录,拼接C++ DLL路径
            string assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string dllPath = Path.Combine(assemblyDir, "Ref_Cpp", "A_Cpp.dll");

            // 加载DLL
            IntPtr dllHandle = LoadLibrary(dllPath);
            if (dllHandle == IntPtr.Zero)
            {
                throw new System.ComponentModel.Win32Exception();
            }

            // 获取函数地址并绑定委托
            IntPtr funcPtr = GetProcAddress(dllHandle, "AddNumber");
            if (funcPtr == IntPtr.Zero)
            {
                throw new System.ComponentModel.Win32Exception();
            }

            _addNumberFunc = Marshal.GetDelegateForFunctionPointer<AddNumberDelegate>(funcPtr);
        }

        public int Do_AddFunction(int num1, int num2)
        {
            return _addNumberFunc(num1, num2);
        }

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
    }
}

这种方式不受DllImport常量限制,只要C++ DLL与C#类库的相对位置不变,下游项目就能正常调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:13:20