「C++学习笔记」面向.Net Core的(C++)CLR类库非专业入门(+使用Opencv)

2023-11-06

关键词:C++/CLR, .Net Core, .Net Famework, Opencv, C#

目录

什么是CLR类库

本文说明

创建Demo程序

调用dll

通过项目引用

通过dll文件引用

其他还没完全清楚的坑:


有关C++/CLI这块的资料真的很少而且都属于翻墙教程(新手找不到门的,和进了门才能懂的)

参考其他资料,以及微软官方说明,以及新建项目时的项目模板说明:

什么是CLR类库

简单的说:

CLR类库,是C++语言的一种扩充,目的是面向C#(.NET)的,

一方面,可以在C++中调用.Net中的方法,让很多原本在C++上很痛苦的工作变简单,并扩大C++的战斗范围。

另一方面,让类库的接口变得.Net友好化,不用每个方法都[dllimport……]了。

抓重点:面向.Net的,带有.Net扩展的C++项目

一定注意,它归根结底是C++项目,我一开始总是会想歪了(总觉得是C#中能使用C++)

------------------------------------------------------------------------

网上有很多这方面的讲解,都比较旧了(那会叫C++/CLI)

其实写这篇文展的几个月之前,VS2019创建项目时,也还是叫“C++/CLI”的,应该时最近才改了名字吧。

大概需要先了解下托管和非托管的区别。原本的C++项目一般都是非托管的代码,而C#是托管代码。

C++/CLI就像一种胶水,或者说桥梁一样,让这两种代码相连

所以也就能看到在同一文件中,"using namespace xx"和"#include <xx.h>"齐飞,"std::cout"和"Console::WriteLine"并存的壮观景象。看起来着实木乱。

本文说明

首先这是一个个人向非专业的入门Demo说明。

需求是这样的,按照原本的方式,我们创建一个C++的dll,在C#中调用的时候,每个方法都需要"[DllImport ....]"先在dll中找到方法,再赋给一个函数指针。具体可以参考我之前的博客:「C++学习笔记」动态链接库(Dll):C++动/静态调用C++的dll

真的是超级头疼,所以有没有一种办法能减缓这种痛苦呢

我找到了C++/CLI

此时我需要C++&OpenCV做一些图像处理相关的工作,封装成dll供.Net Core使用

如果仅仅是.Net Framework平台,可以直接使用OpencvSharp:「图像处理」OpenCV在C#中使用基础(OpenCVSharp)

OpenCV + .Net Core怎么办呢?

于是找到了这个

创建Demo程序

在VS2019新建项目中,搜索CLI或者CLR,找到这个项目模板

输入名称,以我这次【OpcvDllToNetCore】为例:

创建好后会得到如下项目结构(皆有VS自动生成):

像通常一样的方式配置opencv,参考:「图像处理」OpenCV的安装与配置

在【OpcvDllToNetCore.h】中,编写如下代码:

#pragma once

//以下代码使用非托管(opencv是非托管的)
#pragma unmanaged
//取消_M_CEE定义,否则会报很多 不兼容的错误
#undef _M_CEE
#include <opencv2/opencv.hpp>
//opencv包含完了之后,再恢复_M_CEE的定义以及托管声明
#define _M_CEE
#pragma managed

//带上命名空间
namespace OpcvDllToNetCore 
{
	public ref class Opcv
	{
		
	public:
		//调用opencv显示一张图像
		void showImg()
		{
			cv::Mat img = cv::imread("D:\\Demo\\1000\\0001.jpg", cv::IMREAD_COLOR);
			cv::namedWindow("show", cv::WINDOW_NORMAL);
			cv::imshow("show", img);
			cv::waitKey(0);
		}
	};
}

这里说明

1、#pragma unmanaged和#pragma managed

即该行以后按所声明方式编译,即#pragma unmanaged下面的按非托管,#pragma managed按照托管方式

2、#undef _M_CEE 和 #define _M_CEE

这一点不是特别清楚,貌似和windows sdk相关,因为如果不加这一句,会有很多如下报错

“链接规范与前面的xxx不兼容”

这些报错都是windows 10 sdk中的,定位进去就能看到

为了解决这些错误,我把opencv.h的包含放在了_M_CEE定义之外(见前面代码),目前未见其他异常。

然后编译就会生成dll文件。

调用dll

通过项目引用

再添加一个C# 的控制台项目,起名【ConsoleDebug】,注意,这是一个C#项目了

在依赖项中,添加引用,选择前面的【OpcvDllToNetCore】项目。

接着在主函数中引用命名空间,并编写简单调用代码:

using OpcvDllToNetCore;

namespace ConsoleDebug
{
    class Program
    {
        static void Main(string[] args)
        {
            Opcv opcv = new Opcv();
            opcv.showImg();
        }
    }
}

编译运行,会报一些错误,因为缺少opencv的dll,复制到生成的exe的同目录下就好了。

通过dll文件引用

引用项目比较傻瓜式,适合个人开发,多人开发这种可能不方便,一般都是一个人负责dll开发,另一个人使用。

其实方法很简单,把生成的dll复制过来,然后在C#的项目依赖中添加这个dll就好,添加完之后就像使用C#类库一样,引用命名空间,就可以直接使用了,代码和上面的一样。

但是运行起来后报错了,这里有一点要注意!

复制dll过来时,一个时生成的主dll,另一个是所依赖的第三方dll,比如我的opencv_world420.dll,还有个容易被忽略的,就是【Ijwhost.dll】,这个文件是CLR类库生成时一并产生的,从修改时间上看,貌似是一个早就存在的东西,没有这个,就没法正确加载。(其实去研究“引用项目”方式的话可以看到,VS会自动复制这个到exe同目录下的)

其他还没完全清楚的坑:

还遇到了一些坑,但是也稀里糊涂解决的,记录一下,方便有遇到相同问题的

1、总是出现“无法解析的外部命令/符号”

这种一般都是lib没加载对,opencv我习惯用单独的属性配置文件来配置,但是确实写对的,右键项目名,点击属性,重写配一遍就好了,但是再删掉这些,也莫名其妙还是好的,无法理解。

2、总是“试图加载格式不正确的文件”

一般是加的dll依赖的其他dll不全,把前文说的都复制全了,还是会报,删掉重编译,把类库生成的其他文件,包括.pdb、config.json等,一股脑全复制过来就好了,接着再删掉.pdb、.runtimeconfig.json、.deps.json之后,也还是正常的,不是很理解

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

「C++学习笔记」面向.Net Core的(C++)CLR类库非专业入门(+使用Opencv) 的相关文章

  • C++ 返回值、引用、const 引用

    你能向我解释一下返回值 值引用和值常量引用之间的区别吗 Value Vector2D operator const Vector2D vector this gt x vector x this gt y vector y return t
  • 如何在线程创建和退出时调用函数?

    include
  • WP8.1 C# 绑定联系人图像

    信息很简单 我正在尝试创建一个可以显示用户联系人的应用程序 我也是一名自学成才的程序员 所以我在某些方面有编程经验 但总体来说我对数据绑定相对较新 首先 我有一个 ListView 控件 其中包含图像绑定
  • 使用 JSON 格式正确配置 NLog 到 IHostBuilder

    我有以下代码 应该接受 NLog 的 JSON appsettings 配置 然后使用它来创建 NLog LogFactory 这个 NLog 工厂应该被传递到 MyService 类中 以便在那里创建一个记录器 class Program
  • 在调用堆栈中看到大量 clr!CLR Semaphore::Wait

    我们看到很多像下面这样的调用堆栈 我可以知道什么条件 情况会发生这种情况吗 OS Thread Id 0x48654 559 Current frame ntdll NtWaitForSingleObject 0xa Child SP Re
  • 操作/Lambda 表达式内存管理问题

    我将一个操作存储在局部变量中 然后在该局部变量超出范围后使用 使用前是否有被清理的危险 这是一个例子 public List GetMaps Action
  • 宏可以按参数数量重载吗?

    如何this https stackoverflow com q 9183993 153285工作 如何实现 C99 C 11 可变参数宏以仅根据为其提供多少个参数来扩展到不同的事物 编辑 请参阅末尾以获得现成的解决方案 要获得重载的宏 首
  • “包含字符串”的快速索引

    在我的应用程序中 我有多达数百万个短字符串 大部分短于 32 个字符 我想实现一个带有附加列表的搜索框 该列表仅包含包含在搜索框中输入的整个字符串的元素 如何预先建立索引来快速找到此类字符串 所有排序的 STL 容器都会检查整个字符串 对于
  • 将 Python 控制台集成到 GUI C++ 应用程序中

    I m going to add a python console widget into a C GUI below some other controls 许多类将暴露给 python 代码 包括一些对 GUI 的访问 也许我会考虑 P
  • 在 C# 中调用事件处理程序

    我一直在尝试学习如何在 C 中使用事件处理程序 但我无法弄清楚 handler this e 在以下代码中的作用 public event EventHandler ThresholdReached protected virtual vo
  • 在不使用 ncurses 的情况下用 C/C++ 编写“真正的”交互式终端程序,例如 vim、htop...

    不 我不想使用ncurses 因为我想了解如何 终端可以工作 并且我自己编程也很有趣 没有 必须是可移植的 它必须只能在基于 linux xterm 的终端仿真器上工作 我想做的是编写一个交互式终端应用程序 例如 htop 和 vim 我的
  • StreamReader,C#,peek

    我有一个 StreamReader 它偶尔会检查它是否有更多内容可以从简单的文本文件中读取 它使用 peek 属性 问题是 当我使用 peek 时 位置发生了变化 尽管不应该发生 FileStream m fsReader new File
  • 求一个数的因数。无法得到准确的结果

    有人可以帮助纠正我的算法吗 我已经对几个数字进行了测试 但它没有输出完整的因式分解 对于具有大量因子的数字 它完全失败 int num 20 for int i 2 i lt num i if num i 0 cout lt lt i lt
  • C for 循环索引:新 CPU 中的前向索引更快吗?

    在我订阅的邮件列表上 两位知识渊博的 IMO 程序员正在讨论一些优化的代码 并说了以下内容 在 5 8 年前发布的 CPU 上 向后迭代 for 循环稍微快一些 e g for int i x 1 i gt 0 i 因为比较i归零比将其与其
  • 如何强制用户仅使用“new”创建从我派生的类的对象?

    为了实现引用计数 我们使用IUnknown http msdn microsoft com en us library ms680509 VS 85 aspx类接口和智能指针模板类 该接口具有所有引用计数方法的实现 包括Release vo
  • 如何填充两个样条线或直线系列之间的区域

    我有这个Chart 如何填充两个之间的区域Series S0 and S1 说蓝色和黄色Series 为此 我们编写了其中之一Paint事件 这里的ValueToPixelPosition https msdn microsoft com
  • ASP.NET MVC 路由 - 向路由添加 .html 扩展名

    我对 MVC 和路由非常陌生 我被要求修改一个应用程序以使用不同的 url 由于我没有经验 这项任务对我来说有点困难 好吧 让我们谈谈一些代码 routes MapRoute CategoryBySeName Route name prod
  • printf() 使用字符串表“解码器环”调试库

    我写这封信是想看看你们中是否有人见过或听说过我即将描述的想法的实现 我有兴趣为嵌入式目标开发 printf 风格的调试库 目标非常遥远 并且我和目标之间的通信带宽预算非常紧张 因此我希望能够以非常有效的格式获取调试消息 通常 调试语句如下所
  • 清理堆分配对象的良好实践或约定?

    我正在学习C 我有 C C ObjC 背景 相当高级的语言 在 C 或 ObjC 上 作为函数或方法的结果返回堆分配的对象是很简单的 因为对象的清理是受管理的 按照惯例 会在适当的时候销毁 但我不知道在 C 中应该如何处理这个问题 例如 s
  • 从 STL 列表中删除项目

    我想创建一个函数 如果符合特定条件 则将项目从一个 STL 列表移动到另一个列表 这段代码不是这样做的方法 迭代器很可能会被擦除 函数失效并导致问题 for std list

随机推荐

  • PHP发送带附件的电子邮件,使用php发送带附件的电子邮件

    我使用此代码使用php发送带附件的电子邮件 但由于我收到电子邮件并且附件出现在内容中 因此附件中存在错误 在我使用相同的代码并且它成功运行之前 为什么 sending email with attachments function send
  • python设计模式-工厂模式-最简洁的说明与代码

    工厂模式简介 工厂模式实现途径是一个类或者一个方法 通过这个类可以自动化创建出我们想要的对象 工厂模式作用 便于实例化对象 还便于之后增加更多的对象 代码实现 class A pass class B pass class Factory
  • [创业-40]:优秀人与普通人的区别

    0 优秀者是接纳的 口袋 有则改之无则加勉 普通人是踢 皮球 1 优秀者以他人为中心 普通人以自我为中心 2 优秀者遇事先保持冷静 普通人遇事先发泄情绪 3 优秀者善于站在别人的角度思考问题 普通人希望别人站在自己的角度理解自己 4 优秀者
  • Qt unicode字串转中文

    有时候 直接在html里面获取的字符串就是带有 u 的 然后直接显示的时候 u 也会显示出来 这里就是教你如何去掉 u QString filename u6211 u662f u4e2d u6587 do int idx filename
  • 将vscode字体字号调大

    1 进入vscode 2 找到页面左下角齿轮标符点击 然后在弹出选项那里点击设置 setting 3 点击文本编辑器 4 点击字体 5 找到font size点击设置数字 个人建议18 22 即可
  • ‘close’ was not declared in this scope

    close was not declared in this scope 没有包含头文件 unistd h 造成的 加上 include
  • Spring Cloud 学习笔记二:搭建微服务工程之Eureka 注册中心开启安全认证

    目录 Eureka 注册中心开启密码认证 Eureka 注册中心开启密码认证 Eureka 自带了一个 Web 的管理页面 方便我们查询注册到上面的实例信息 但是有一个问题 如果在实际使用中 注册中心地址有公网 IP 的话 必然能直接访问到
  • 如何在30天内,通过TikTok变现一万美金。按照我的方法,你也可以

    大家好 我是项柚 最近创作者基金愈发火热 Tiktok又热了起来 但还是很多朋友停留在川普封停TT的时间节点上 一直没有时间 今天特意写一篇文章来详细分析 其实圈子很重要 方向很重要 所以很多Tiktok运营者做不好的原因是没有交流的圈子
  • [HFCTF2020]EasyLogin

    知识点 jwt伪造 jwt 全称 Json Web Token 是一种令牌格式 可以用来区分各个用户 形式是下面这样 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 eyJzZWNyZXRpZCI6MSwidXNl
  • GitHub C 和 C++ 开源库的清单(含示例代码)

    内容包括 标准库 Web应用框架 人工智能 数据库 图片处理 机器学习 日志 代码分析等 标准库 C 标准库 包括了STL容器 算法和函数等 C Standard Library 是一系列类和函数的集合 使用核心语言编写 也是C ISO自身
  • PintOS lab2 User Programs 实验记录

    Background 大体流程如下图所示 显然这时候start process无法被调度到 然后start process 里面load out文件 o文件就是对象文件 是可重定向文件的一种 通常以ELF格式保存 里面包含了对各个函数的入口
  • 教你手机如何查看真实的IP地址

    有朋友不会查询自己手机的IP地址 很多时候我们需要使用vpn切换手机当前的IP 如何判断我们切换IP成功了呢 今天站长就教你手机如何查看目前真实的IP地址 1 打开手机浏览器 2 在搜索框里输入 ip 然后点击搜索 在搜索结果页面就会显示你
  • ESP32 上快捷部署 Tensorflow lite 机器学习(TinyML)

    在这篇文章中 我将向您展示使用 Arduino IDE 将 TensorFlow Lite 模型部署到 ESP32 的最简单方法 无需任何编译内容 Arduino 库 这个 Arduino 库是为了简化使用 Arduino IDE 将用于微
  • 4.8xml于json

    HTTP 协议 HyperText Transfer Protocol 超文本传输协议 是 TCP IP 协议集中的协议 是一个简单的请求 响应协议 指 定了客户端发送给服务器的消息以及服务器的响应 所有的 WWW 文件都必须遵守这个标准
  • matplotlib绘制饼状图

    源自http blog csdn net skyli114 article details 77508430 ticket ST 41707 PzNbUDGt6R5KYl3TkWDg passport csdn net pyplot使用pl
  • 接口测试基础

    目录 一 接口及接口测试概念 1 接口 接口的类型 2 接口测试 二 HTTP协议 1 HTTP协议的特点 2 URL格式 3 HTTP请求 4 HTTP响应 三 接口规范 1 传统风格接口 2 RESTful风格接口 四 接口测试流程 1
  • Python 11. OpenCV 透视变换

    import cv2 import numpy as np from matplotlib import pyplot as plt img cv2 imread pic4 PNG rows cols img shape 2 cv2 ims
  • 支持图文转换!PSD文档处理工具Aspose全新升级

    Aspose PSD是高级PSD和入门级AI文件格式操作API 允许创建和编辑Photoshop文件 并提供更新图层属性 添加水印 执行图形操作或将一种文件格式转换为另一种文件的功能 没有任何Adobe Photoshop或Adobe Il
  • [系统

    系统环境说明 系统 Deepin V20 平台 amd64 参考文献 asdf maven asdf document asdf plugins asdf vm安装 见多版本管理命令行工具asdf vm安装及使用 asdf vm安装Mave
  • 「C++学习笔记」面向.Net Core的(C++)CLR类库非专业入门(+使用Opencv)

    关键词 C CLR Net Core Net Famework Opencv C 目录 什么是CLR类库 本文说明 创建Demo程序 调用dll 通过项目引用 通过dll文件引用 其他还没完全清楚的坑 有关C CLI这块的资料真的很少而且都