在 C# 中使用 C++

C#调用C++函数 C#主要通过命名空间System.Runtime.InteropSerivces中的关键字DllImport关键字来实现调用C++函数,参数的引用传递则通过序列化来实现(ref/out关键字及IntPtr指针类型),结构体的序列化采用StructLayout标签。 1. 使用DllImport关键字来调用C++函数,所声明的函数必须为static exten类型: [DllImport("us 阅读详情

综述

C# 调用 C++ 中的函数或类是通过调用其 dll 来实现的。对于 unmanaged C++,我们在每个函数前加上 dllexport,并在 C# 代码中通过 dllimport 和 extern static 来调用 dll 中的函数。这样需要为每个函数添加 dllimport/dllexport,很不方便。注意 C# 是可以直接调用 C++/CLR (managed C++) 的 dll 的。因此,为了两端(调用端/实现端)代码编写的便利,我们可以用 C++/CLR 作为联系 unmanaged C++ 和 C# 的 wrapper,写出更简洁的代码。

C# 调用 C++ 代码 —— dllimport 方式

编写 C++ DLL

新建 VC++ 控制台空项目,项目类型选 DLL,新建 MathFuncDll.h 和 MathFuncDll.cpp 文件,代码如下:

// MathFuncsDll.h
#include <stdexcept>
using namespace std;

namespace MathFuncs
{
   extern "C" { __declspec(dllexport) double Add(double a, double b); }
   extern "C" { __declspec(dllexport) double Subtract(double a, double b); }
   extern "C" { __declspec(dllexport) double Multiply(double a, double b); }
   extern "C" { __declspec(dllexport) double Divide(double a, double b); }
}
// MathFuncsDll.cpp
#include "MathFuncsDll.h"

namespace MathFuncs
{
    double Add( double a, double b )
    { return a+b; }
    double Subtract( double a, double b )
    { return a-b; }
    double Multiply( double a, double b )
    { return a*b; }
    double Divide( double a, double b )
    {
       if ( b == 0 )
            throw invalid_argument("b cannot be zero!");
       return a/b;
    }
}

编译后在 Debug 或 Release 文件夹中可找到 MathFuncsDll.dll 文件。

编写 C# 测试程序

新建 C# 控制台项目,Program.cs 的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace cppdll_test_csharp
{
    class Program
    {
        [DllImport("C:/Users/huanglianghua/Documents/Visual Studio 2012/Projects/cppdll_test/Debug/cppdll_test.dll",
            CallingConvention = CallingConvention.Cdecl)]
        public static extern double Add(double a, double b);

        static void Main(string[] args)
        {
            double c = Add(10, 10);
            Console.WriteLine(c);
        }
    }
}

运行后输出 20 代表程序正确。

C# 调用 C++ 代码 —— C++ wrapper 方式

以上代码能够正确运行。但是需要 dllimport/dllexport,且调用时每个函数需要定义 static extern。当函数数量不多时,这种方法容易使用。但当函数数量很大时,调用会很不方便。

注意到虽然 C# 调用普通的 C++ 代码(unmanaged C++)很麻烦,但 C# 是可以直接调用 C++/CLI (managed C++) 的 dll 的。C++/CLI 即托管的 C++ —— 以 C++ 的名义写 C#。CLI 是 Common Language Infrastructure 的缩写。所以我们可以将 C++/CLI 作为 C++ 和 C# 的接口 —— 为 C++ 程序写一个 wrapper,然后在 C# 里直接调用。

简而言之,需要三个项目:

  • 一个 VC++ 项目,采用 unmanaged C++,编写主要的函数体;
  • 一个 VC++ 项目,采用 managed C++,编写 C++/CLI wrapper;
  • 一个 VC# 项目,测试 C++/CLI wrapper 的 dll。

C++ 主体代码

建立 VC++ 空项目,项目类型为控制台应用程序,建立 MathFuncs.h, MathFuncs.cpp 和 main.cpp 文件,其中 main.cpp 主要用于测试 MathFuncs.cpp 中的函数。代码如下:

// MathFuncs.h
#pragma once

#include <stdexcept>
using namespace std;

class MyMathFuncs
{
public:
    double Add(double a, double b);
    double Subtract(double a, double b);
    double Multiply(double a, double b);
    double Divide(double a, double b);
};
// MathFuncs.cpp
#pragma once
#include "cli_cpp.h"

double MyMathFuncs::Add(double a, double b)
{ return a+b; }

double MyMathFuncs::Subtract(double a, double b)
{ return a-b; }

double MyMathFuncs::Multiply(double a, double b)
{ return a*b; }

double MyMathFuncs::Divide(double a, double b)
{
    if ( b == 0 )
       throw invalid_argument("b cannot be zero!");
}
// main.cpp
#include <stdio.h>
#include "cli_cpp.h"

using namespace std;

int main()
{
    MyMathFuncs* m = new MyMathFuncs();
    double c = m->Add (10.1,20.2) ;

    printf("Result is %f\n", c);
    free(m);
    return 0;
}

代码无误的话运行会出现 “Result is 30.300000”。

C++ wrapper 代码

新建 VC++ CLI Class Library 项目 managedDllWrapper,修改 managedDllWrapper.h 和 managedDllWrapper.cpp 如下:

// managedDllWrapper.h
#pragma once

#include "C:\Visual Studio 2012/Projects/MathFuncs/MathFuncs.h"
#include "C:\Visual Studio 2012/Projects/MathFuncs/MathFuncs.cpp"

using namespace System;

namespace managedDllWrapper {
    public ref class MyMathFuncsWrapper
    {
    public:
       // constructor
       MyMathFuncsWrapper();

       // wrapper methods
       double AddWrapper ( double a, double b);
       double SubtractWrapper ( double a, double b);
       double MultiplyWrapper ( double a, double b);
       double DivideWrapper ( double a, double b);

       // public variable
       double initVal;

    private:
       MyMathFuncs* myCppClass; // an instance
    };
}
// managedDllWrapper.cpp
#include "stdafx.h"
#include "managedDllWrapper.h"

#include "C:\Visual Studio 2012/Projects/MathFuncs/MathFuncs.h"
#include "C:\Visual Studio 2012/Projects/MathFuncs/MathFuncs.cpp"

// Constructor implementaion
managedDllWrapper::MyMathFuncsWrapper::MyMathFuncsWrapper()
{
    initVal = 20.0;
    myCppClass = new MyMathFuncs(); //initiate C++ class's instance
}

double managedDllWrapper::MyMathFuncsWrapper::AddWrapper ( double a, double b)
{
    return myCppClass->Add(a,b);
}

double managedDllWrapper::MyMathFuncsWrapper::SubtractWrapper (double a, double b)
{
    return myCppClass->Subtract(a,b);
}

double managedDllWrapper::MyMathFuncsWrapper::MultiplyWrapper (double a, double b)
{
    return myCppClass->Multiply(a,b);
}

double managedDllWrapper::MyMathFuncsWrapper::DivideWrapper (double a, double b)
{
    return myCppClass->Divide(a,b);
}

以 Debug 或/和 Release 模式编译后会生成 managedDllWrapper.dll 文件。我们将在 C# 中使用它们。

C# 测试代码

新建 C# 控制台应用程序,在 References 中右键添加,选择 Browse... 找到 managedDllWrapper.dll 并添加,即可直接在 C# 代码中使用 dll 中的函数。C# 测试代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using managedDllWrapper;

namespace testCSharpInterface
{
    class Program
    {
        static MyMathFuncsWrapper mymath = new MyMathFuncsWrapper();

        static void Main(string[] args)
        {
            double c = mymath.initVal;
            Console.WriteLine(c);

            c = mymath.AddWrapper(c, c);
            Console.WriteLine(c);
        }
    }
}

运行无误应该出现结果 20 和 40。

C# 调用 C++ OpenCV 代码

在 rich UI 的 C# 中调用 rich efficiency 的 C++ OpenCV 代码,结合二者的优势。

参考链接

  1. Use C++ codes in a C# project — unmanaged C++ solution
  2. Youtube 视频 DLL (C++) for C sharp (C#)
  3. Use C++ codes in a C# project — solution of wrapping native C++ with a managed CLR wrapper
  4. Use OpenCV C++ codes in a VC# project — solution of creating a managed CLR wrapper
在C#中使用C++编写的类 现在在Windows下的应用程序开发,VS.Net占据了绝大多数的份额。因此很多以前搞VC++开发的人都转向用更强大的VS.Net。在这种情况下,有很多开发人员就面临了如何在C#中使用C++开发好的类的问题。下面就用一个完整的实例来详细说明怎样用托管C++封装一个C++类以提供给C#使用。 比如,现在有一个工程名为NativeCppDll的由C++编写的DLL,里面输出了一个CPe 阅读详情

相关推荐

C++ 打包成lib,在C#中使用

C++ 打包成lib,在C#中使用

qq_33416262的博客 1129

如何在C#代码中调用C++函数 (一)

目录 背景介绍: C++工程项目封装为DLL库: 具体调用: 常见错误: 参考资料: 背景介绍: .NET平台下的互操作有三种方式:平台调用,C++ Interop和COM Interop。 平台调用: 平台调用服务(英语:Platform Invocation Services),或称P/Invoke,通常指微软的公共语言运行时提供的跨平台调用方式。 平台调用服务是公共语言基...

ukulele-gitara的专栏 1万+

C#使用Tesseract C++ API过程记录

此外,vcpkg还具有版本控制功能,能够方便地切换库的不同版本。Tesseract提供了丰富的 API 接口,支持 C++、Python、Java、Node.js 等多种编程语言,没有C#的,实际上已经有大佬做了C#的封装了,并提供了一个示例项目,需要只是简单使用一下,用这个大佬的就很方便了。之前跟大家分享的TesseractOCR-GUI需要在电脑上安装Tesseract才能用,因为只是简单的对Tesseract的命令行使用做了封装,现在通过这种方法,不需要安装Tesseract也能使用了。

xdpcxq1029的博客 1208

C# 调用C++代码

平时我们写的C#动态库,在VS中直接添加引用,然后调用DLL中的方法就好了,但是用C++生成的DLL并不行,在一般项目中,用不到C#调用C++代码的情况,但在上位机,工控行业很常见,视觉,人工智能行业中,算法很多都是C++写的,而上位机大部分都是C#开发的,那么这篇文章就从头开始,教你如何从创建一个简单的C++项目,到C#的调用。............

熊思雨的博客 1万+

C#实现调用C++的三种方法(附完整源码)

C#实现调用C++的三种方法(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1971

C++ 与 C# 代码互相调用

C++ 和 C# 代码的互相调用为软件开发带来了更多的灵活性和功能扩展性,通过多种方式如动态链接库、COM 组件、C++/CLI 以及代理存根机制等,可以根据不同的应用场景和需求实现两者之间有效的交互。然而,在实现互调的过程中,也面临着诸多挑战,包括数据类型转换、内存管理、调试困难以及性能优化等方面的问题,需要开发者充分了解两种语言的特点、互调机制的原理以及相关的工具和技术,才能顺利地完成跨语言的代码集成,开发出高质量、高性能的软件系统。

candy的博客 3232

在C++中使用C#编写的类

在那篇《在C#中使用C++编写的类》中我介绍了如何在C#中使用C++编写的类。可是由于C#在用户界面设计、数据库存储和XML文件读取等方面的优势,有时候也会出现要在C++中使用C#编写的类的情况。下面就用一个完整的实例来说明怎样在C++中使用C#编写的类。 比如说,现在有一个用C#编写的DLL工程CsharpDll里面有一个Person类://Person.cs

寒星轩 1万+

CPRI原理及应用--帧结构

对于CPRI 控制字,协议将1个超帧(256基本帧)的控制数据划分为一个“子通道”,将子通道内超帧内的控制字进行行列划分,分为4列X64行,每64个基本帧组成1列。如下图所示。每个Xs子通道内Ns的定义基本相同,在做控制字设计时,主要已Xs和Ns和X.Y.Z开展控制字映射。

u014035968的博客 2325

C# 使用C++调用C#的DLL

简述 我们有时候需要在C++程序中去使用一些C#程序的代码,但是又不想弄的太麻烦,或者是我们想要使用别人写好的C#库,那么该怎么办呢?最方便的就是把C#编译成dll,然后用再在C++中去调用。 目录 一、C#项目生成DLL (一)、新建项目生成dll (二)、已有项目生成dll 二、调用C#的dll (一)、在C#项目中调用C#的dll (2)C++调用C#的dll——直接调用 ...

Sakuya__的博客 2171

Ultrascale/Ultrascale+ FPGA GTH IP及结构详解(一)

FPGA GTH Transceiver

houzi6320的博客 1万+

保姆级教程:在RK3568上搞定PR2100K+GC2385双摄(从DTS配置到HAL层补丁)

本文详细介绍了在RK3568平台上调试PR2100K+GC2385双摄系统的完整流程,从DTS配置到HAL层补丁。涵盖硬件连接、媒体控制器拓扑验证、Camera3配置、HAL层特殊补丁及性能优化等关键步骤,帮助开发者快速解决双摄调试中的常见问题,提升嵌入式视觉系统开发效率。

weixin_28724661的博客 195

如何在C#中使用C++类

如何在C#中使用C++类(非托管)和C函数 vip https://blog.youkuaiyun.com/bruce135lee/article/details/80028788 C#调用的C++库的使用(三种方式)https://blog.youkuaiyun.com/weixin_41225491/article/details/82593839 C#调用C/C++ DLL 参数传递和回调函数的总结 ht...

jadesl的专栏 1216

基于Python的携程景点评价爬虫与情感评分分析

摘要: 本项目通过Python技术栈实现携程景点评论的情感分析系统,包含数据爬取、文本预处理、情感评分和可视化分析全流程。使用requests抓取评论接口,jieba进行中文分词,SnowNLP计算情感得分(0-1),并通过词云、情感分布图呈现结果。典型分析显示72%评论为正面,负面反馈多涉及"排队久""票价贵"等问题。系统可辅助景点口碑管理,扩展方向包括多景点对比、BERT模型优化等。项目强调需遵守爬虫伦理,控制请求频率,适用于非商业用途的旅游数据分析。(150字)

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 977

在C#中使用C++代码

原文:http://xiali.spaces.live.com/blog/cns!473068a9be0aa907!391.entry?wa=wsignin1.0手头上有不少的C++代码算法,不打算重写,但是希望利用一下。所以希望能够在C#中使用C++代码。目前为止,我对CLR的理解就是,这个是用来帮助我们在C#中来利用C++的东西的一个手段。因为在CLR的方式下,我们可以调用unmanage

牛牛工作室 3143

uniapp - 实现PDA扫码枪RFID批量扫描读取示例代码,uni-app APP识别RFID(射频识别)结合硬件设备进行扫描,uniApp调用RFID读写通用方案适配各种设备+完整实例源码教程!

uni-app PDA 读取RFID,基于uniapp开发PDA扫码枪APP:实现RFID批量扫描读取功能,UniApp中的RFID实现,手持机 RFID插件(uni-app集成手持设备rfid插件),uniapp自动识别RFID,uni-app调RFID模块,uni-app RFID识别插件,uniapp读取rfid,uniapp手持设备扫描rfid,uniapp超高频rfid识别,rfid标签识别,uniapp调用RFID读写,uniapp rfid扫码枪,uniapp中如何使用rfid插件,打包上线后

🏆 前端领域优质创作者 1万+

华为 MetaERP 通过元数据驱动的多组织架构 + 内部交易协同 + 自动对账引擎 + 合并规则引擎,实现多组织内部往来与合并报表的全流程自动抵消,核心是源头标准化、过程自动化、结果可追溯

摘要: 华为MetaERP通过元数据驱动的多组织架构与主数据标准化,实现内部往来与合并报表全流程自动化。其核心包括:统一组织模型与主数据(确保数据口径一致)、内部交易协同(自动生成对称凭证)、智能对账引擎(多维度自动匹配差异)、合并规则引擎(配置化抵消模板)。依托GaussDB高性能数据库与流批一体架构,华为全球88家子公司合并报表效率提升400%,关账时间缩短至2小时,支持多准则、多币种自动抵消,审计全程可追溯。相比传统ERP,MetaERP在协同性、自动化与扩展性上优势显著,为跨国集团提供高效、准确的合

金牌架构师 264

C++编程笔记:在C#中使用C++编写的类

现在在Windows下的应用程序开发,VS.Net占据了绝大多数的份额。因此很多以前搞VC++开发的人都转向用更强大的VS.Net。在这种情况下,有很多开发人员就面临了如何在C#中使用C++开发好的类的问题。下面就用一个完整的实例来详细说明怎样用托管C++封装一个C++类以提供给C#使用。 比如,现在有一个工程名为NativeCppDll的由C++编写的DLL,里面输出了一个CPerson...

一片雾霾的博客 205

[ vulhub漏洞复现篇 ] Drupal XSS漏洞 (CVE-2019-6341)

[ vulhub漏洞复现篇 ] Drupal XSS漏洞 (CVE-2019-6341) Drupal是使用PHP语言编写的开源内容管理框架(CMF),它由内容管理系统(CMS)和PHP开发框架(Framework)共同构成,在GPL2.0及更新协议下发布。Drupal在某些情况下,通过文件模块或者子系统上传恶意文件触发XSS漏洞。

qq_51577576的博客 2208

如何在C#中直接使用dll中的C++类

然后再新建一个CLR工程,名字就叫做CppClr吧,用C++\CLI语言对Cpp dll做一个包装(制作胶水),记得添加对Cpp dll的引用。C#和C++是两种编程语言,直接在C#中使用C++类是很困难的,但万能的微软提供了C++/CLI这一工具作为胶水,把两者粘连起来的。C++\CLI这胶水还是比较好用的,相当于给dll 里的C++类重新写了一个头文件,让C# 能够认识。好了,胶水制作好了,可以在C# 工程里试一下,建立一个控制台项目吧,名字就叫做App好了。

manyoudian的博客 677

手把手教你ensp仿真搭建校园网(含防火墙及无线网络)系列(三)校园无线网络AC+AP配置

本系列博客将带你从零开始,使用 华为 eNSP(Enterprise Network Simulation Platform) 仿真搭建一个完整的校园网络,涵盖 核心层、汇聚层、接入层、防火墙安全策略、无线AC+AP组网 等实战场景。无论你是网络初学者还是希望深化实战经验的工程师,都能通过本教程掌握企业级网络的规划、配置与排错技巧。

echo的博客 1357

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

c# 引用c语言dll文件,C#直接使用DllImport调用C/C++动态库(dll文件)

1.C/C++动态库的编写下面是我编写的一个比较简单的C++dll文件用来测试,关于如何编写dll文件,我这里便不再赘述,不懂得自行查询,(1).h文件#ifdef MYDLL_EXPORTS#define MYDLL_API __declspec(dllexport)#else#define MYDLL_API __declspec(dllimport)#endif//求两个整数的和(普通类型的...

weixin_39816062的博客 1479

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C# 中使用C++导出的DLL文件

摘要本篇博客主要介绍使用C++生成DLL库,并在C#工程之中进行调用。本技术可以用于Unity开发中,可以将一些复杂计算量较大的工作使用C++编写,生成DLL文件后在Unity中使用C#脚本进行调用。

ChaoQun 2810

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

上一篇: CNN 简史与 Keras 增量实现(一)—— Softmax 分类器
下一篇: Apache Thrift 配置和使用指南
withchris
博客等级 码龄11年 215粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值