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

如何正确将C++/CLR包装器链接到非托管C++ DLL并在C#中使用

解决非托管C++ DLL与C++/CLR包装器、C#项目的兼容配置问题

我之前也碰到过完全一样的问题,核心症结在于非托管DLL不能直接作为程序集引用给CLR项目,而且运行时CLR进程需要能定位到非托管DLL的位置。下面是一步步的具体解决办法:

一、统一非托管C++ DLL的编译基础配置

  1. 对齐平台工具集:
    右键非托管项目 → 属性 → 配置属性 → 常规 → 平台工具集,选择和你的C++/CLR项目完全一致的版本(比如VS2017对应的v141),避免因工具集版本差异导致的兼容性问题。
  2. 统一目标平台架构:
    确保非托管项目、CLR项目、C#项目的目标平台完全一致(要么全是x86,要么全是x64),跨架构的依赖会直接导致加载失败。操作路径:右键项目 → 属性 → 配置属性 → 常规 → 平台。
  3. (可选)统一输出目录:
    把非托管项目的输出目录改成和CLR项目一致,比如设置为$(SolutionDir)$(Configuration)\,这样编译后两个DLL会自动放在同一个文件夹,减少运行时的路径问题。操作路径:右键非托管项目 → 属性 → 配置属性 → 常规 → 输出目录。

二、正确在C++/CLR项目中关联非托管DLL

非托管DLL不能直接通过“添加引用”关联,要通过链接器配置来实现:

  1. 添加头文件路径:
    右键CLR项目 → 属性 → 配置属性 → VC++目录 → 包含目录,添加非托管项目的头文件所在路径(比如../Project2/)。
  2. 添加库文件路径:
    同样在VC++目录 → 库目录,添加非托管项目的输出目录(比如$(SolutionDir)$(Configuration)\),让链接器能找到非托管DLL对应的.lib文件。
  3. 配置链接器依赖:
    进入链接器 → 输入 → 附加依赖项,添加非托管DLL对应的.lib文件名(比如Project2.lib)—— 只要你在非托管代码里用了__declspec(dllexport),编译时默认会生成这个.lib文件。

三、确保运行时非托管DLL可被找到

即使编译通过,CLR进程(也就是你的C#程序)运行时必须能找到非托管DLL,这里推荐几种靠谱的方式:

  1. 自动复制到C#输出目录:
    右键非托管项目 → 属性 → 生成事件 → 后期生成事件 → 命令行,添加复制命令:
    copy "$(TargetPath)" "$(SolutionDir)ConsoleApp3\bin\$(Configuration)\"
    
    这样每次编译非托管项目,都会自动把DLL复制到C#程序的运行目录。
  2. 临时添加环境变量(仅开发阶段用):
    把非托管DLL的输出目录添加到系统PATH环境变量里,CLR进程会自动从PATH路径查找依赖。
  3. 代码中指定路径(灵活但需要额外代码):
    在C#程序启动时,通过调用Win32 API的SetDllDirectory方法,手动指定非托管DLL的存放路径。

四、代码细节优化(避免名字修饰问题)

你的代码里可以加个小优化:给非托管函数加上extern "C",避免C++的名字修饰导致CLR项目找不到函数。修改非托管头文件UnmanagedHeader.h:

// UnmanagedHeader.h
#pragma once
extern "C" __declspec(dllexport) void HelloDLL();

按照上面的步骤配置完成后,重新编译所有项目,运行C#程序应该就能正常调用非托管DLL的函数了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:08:10