新闻中心

C#如何调用C++的DLL?P/Invoke与C++/CLI动态链接库调用方法详解

2025-11-25
浏览次数:
返回列表
答案是P/Invoke适用于简单C风格函数调用,C++/CLI适合复杂C++类交互;前者轻量但受限,后者灵活但需托管包装。

c#如何调用c++的dll?p/invoke与c++/cli动态链接库调用方法详解

在C#中调用C++编写的DLL,主要有两种方式:P/Invoke(平台调用)和C++/CLI。选择哪种方式取决于你的需求、性能要求以及是否需要跨语言复杂类型交互。

P/Invoke:适用于纯C风格导出函数

当C++ DLL以C接口形式导出函数(即使用extern "C"防止C++名称修饰),并且传递的是基本数据类型或简单结构体时,推荐使用P/Invoke。

步骤如下:

  • 确保C++ DLL导出C兼容函数
  • 在C#中声明对应的DllImport方法
  • 正确映射参数和返回值类型

C++ DLL 示例(mycppdll.h):

extern "C" {
  __declspec(dllexport) int Add(int a, int b);
  __declspec(dllexport) void GetString(char* buffer, int bufferSize);
}

C# 调用代码:

using System;
using System.Runtime.InteropServices;

class Program {
  [DllImport("mycppdll.dll", CallingConvention = CallingConvention.Cdecl)]
  public static extern int Add(int a, int b);

  [DllImport("mycppdll.dll", CallingConvention = CallingConvention.Cdecl)]
  public static extern void GetString(StringBuilder buffer, int bufferSize);

  static void Main() {
    int result = Add(3, 5);
    Console.WriteLine("Add result: " + result);

    var sb = new StringBuilder(256);
    GetString(sb, sb.Capacity);
    Console.WriteLine("String from C++: " + sb.ToString());
  }
}

注意事项:

  • 调用约定必须匹配(常见为Cdecl或StdCall)
  • 字符串传递需使用StringBuilder或IntPtr配合Marshal操作
  • 复杂结构体需用StructLayout和MarshalAs显式布局

C++/CLI:桥接C++与.NET的中间层

当你需要调用C++类、模板、STL容器,或者涉及复杂的对象生命周期管理时,P/Invoke难以胜任。此时应使用C++/CLI创建一个“托管包装器”DLL。

优点:

美图云修 美图云修

商业级AI影像处理工具

美图云修 50 查看详情 美图云修
  • 可直接调用原生C++类和方法
  • 支持面向对象设计(如继承、多态)
  • 自动处理内存和异常转换

实现步骤:

  1. 创建C++/CLI类库项目(.NET Framework)
  2. 包含原生C++头文件并链接LIB文件
  3. 编写ref class作为托管接口
  4. C#项目引用生成的DLL

C++/CLI 包装示例(Wrapper.h):

// 原生C++类
class NativeMath {
public:
  int Multiply(int x, int y);
};

// 托管包装类
public ref class ManagedMath {
private:
  NativeMath* native;

public:
  ManagedMath() {
    native = new NativeMath();
  }

  ~ManagedMath() {
    delete native;
  }

  int Multiply(int x, int y) {
    return native->Multiply(x, y);
  }
};

C# 调用代码:

class Program {
  static void Main() {
    var math = new ManagedMath();
    int result = math.Multiply(4, 7);
    Console.WriteLine("Multiply result: " + result);
  }
}

关键点:

  • C++/CLI项目输出为混合程序集(含托管和本地代码)
  • 必须针对具体平台编译(x86/x64),不支持AnyCPU
  • 注意异常转换(C++异常不能直接抛给C#

如何选择合适的方法?

根据实际场景判断:

  • 如果DLL只提供简单函数接口,且参数为int、double、char*等基础类型,用P/Invoke更轻量
  • 若需调用C++类、重载函数、虚函数或多态行为,C++/CLI是唯一可行方案
  • 团队具备C++能力时,C++/CLI灵活性更高;否则优先考虑封装成C接口

基本上就这些。两种方式都能有效打通C#与C++的壁垒,关键是理解各自边界和适用范围。

以上就是C#如何调用C++的DLL?P/Invoke与C++/CLI动态链接库调用方法详解的详细内容,更多请关注其它相关文章!


# 游戏开发  # 陕西seo优化专业定制  # 广州仓储seo团队招聘  # 养生食品营销推广方案  # 重庆网站推广行者seo09  # 綦江seo优化排名推广  # 关键词霸屏方案seo  # 桐城百度网站优化  # 徐州网站推广 必选c金石下拉_强  # 崇左营销推广网络营销招聘  # 网站建设如何做好服务  # 新特性  # 的是  # app  # 动态链接库  # 适用于  # 你在  # 面向对象  # 有哪些  # 多态  # 美图  # lsp  # .net  # c#  # c++  # ai 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 解决Python单元测试中Mock异常方法调用计数为零的问题  《明末:渊虚之羽》设计师谈设计角色:那会刚毕业 充满激情  QQ邮箱登录平台入口 QQ邮箱网页版邮箱官方入口  蛙漫漫画官网在线入口 蛙漫全本漫画免费阅读平台  一加 14R 快充无反应_一加 14R 充电优化  Lar*el的路由模型绑定怎么用_Lar*el Route Model Binding简化控制器逻辑  PHP表单数据传递:如何通过隐藏输入字段获取动态ID  必由学官方登录入口 必由学教师学生账号快速访问  163邮箱登录密码 163邮箱忘记密码找回  C#如何安全地从用户上传的XML文件中读取数据? 验证与清理策略  印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】  PPT平滑切换怎么做 PPT炫酷“平滑”切换动画制作教程【必学】  中兴BladeV30怎样用测距估书架层高_iPhone中兴BladeV30测距估书架层高【家装参考】  怎样更改Windows系统的默认安装路径_避免C盘爆满的终极设置【技巧】  AO3最新可访问网址 Archive of Our Own官方在线入口  在J*a中如何隐藏复杂性_使用门面模式组织对象交互  利用Bokeh CustomJS动态控制DataTable列可见性  蛙漫移动版在线看 蛙漫手机浏览器直达入口  html两个JS只运行一个怎么办_让双JS在html中都运行方法【技巧】  poki免费入口快捷访问 poki人气小游戏直接玩站点  CSS Flexbox如何实现多行排列_flex-wrap wrap自动换行显示  iCloud登录入口网页版 苹果iCloud官网登录  厨房不锈钢水槽发黑生锈怎么处理_水槽用可乐+锡纸2分钟抛亮如新  2026春节假期票务安排_2026春节放假购票指南  自定义Bag-of-Words实现:处理带负号的词汇权重  J*aScript map 方法中处理循环元素为空数组的策略  C++如何实现一个装饰器模式_C++设计模式之动态地给对象添加额外职责  免费抖音短视频入口_抖音网页版短视频免费通道  Go语言中动态执行代码字符串的策略与实践  MAC如何安全彻底地删除文件_MAC使用终端命令确保文件无法被恢复  MAC的“快捷指令”怎么同步到iPhone_MAC利用iCloud同步所有设备的自动化指令  如何使用Go和Martini动态服务解码后的图片  荣耀Play7T运行卡顿解决_荣耀Play7T性能优化  铁路12306官网网页端快速入口 铁路12306官方首页登录教程  内存检查:在VS Code中调试C++时的内存视图  电脑屏幕颜色不舒服怎么办_Windows夜间模式与色彩校准教程【护眼技巧】  sublime如何只显示或隐藏特定类型文件_sublime侧边栏文件过滤  J*aScriptWebpack优化_J*aScript构建工具实战  在J*a中如何开发简易电子商务商品管理系统_商品管理系统项目实战解析  期待已久:小米17 Ultra、小米首款NAS本月登场  J*aScript中赋值与自增运算符的复杂交互与执行机制  AO3同人作品网入口 AO3搜索引擎官网永久地址  美团外卖商家服务中心入口 美团商家版官网入口  Android Studio计算器C键功能异常排查与修复教程  MongoDB Aggregation:在嵌套对象数组中精确匹配ObjectId  不同用户不同价格! 索尼开启账户个性化定价测试  Windows10怎么开启夜间模式 Windows10系统设置调整色温与亮度缓解夜间用眼疲劳【教程】  解决Python logging 中 datefmt 导致时间戳固定不变的问题  J*a里如何实现线程安全的懒加载单例_懒加载单例实现方法解析  如何修改开机登录密码_Windows账户安全设置超详细教程【必学】 

搜索