C#与OpenCV C++导出DLL调用与数据交互

科技   2024-11-27 23:26   江苏  

点击上方蓝字关注我们

微信公众号:OpenCV学堂

关注获取更多计算机视觉与深度学习知识

引子

最近一直在搞OpenCV实验大师工作流引擎的C#支持,已经完成大部分C++ SDK导出支持C#调用。总结记录一下遇到各种问题。

C++ DLL

C++中的支持流程很简单:
第一:在VS中建立一个C++ DLL空项目第二:构建C++ DLL的代码或者类库第三:声明导出函数接口与实现
完成这三步就可以了,上述方式默认是非托管的,别问我什么是托管的方式,我觉得非托管的能用就可以了。但是很多博客上面说的让人云山雾绕。

一个简单的实现如下:
#pragma once
#ifdef _DLL_EXPORTS#define DLL_API _declspec(dllexport)#else#define DLL_API _declspec(dllimport)#endif
#include <opencv2/opencv.hpp>
//=========导出函数C++调用接口============class DLL_API MyTestDLL {public: int addData(int a, int b); ~MyTestDLL();};

相关类的实现如下:

#define _DLL_EXPORTS#include <mytest.h>
MyTestDLL::~MyTestDLL() {std::cout << "destory instance done!" << std::endl;}
int MyTestDLL::addData(int a, int b) { int sum = 0; sum = a + b; std::cout << "sum: " << sum << std::endl; return sum;}
导出类支持的DLL接口函数如下:
extern "C" __declspec(dllexport) void* __stdcall createInstance();extern "C" __declspec(dllexport) bool __stdcall addData(void* p, int a, int b);

然后完成相关实现C++代码即可。

C++ 与C# 数据交换

既然让C#调用C++,就必须知道C++中的各个方法参数在C#中是如何表示,如何初始化,如何传给C++,如何返回数据给C#,这块才是C#调用C++ 最容易出问题的地方。因此本人总结了几种不同的数据传输方法。


图像数据传递方式:

C++中的接口定义

extern "C" __declspec(dllexport) bool __stdcall mergeImg(uchar * src, int w, int h);

C#中的导出接口定义

[DllImport("your_test_name.dll")]static extern bool mergeImg(IntPtr src, int w, int h);
就是把图像数据数组在C#转为INTPtr指针,然后再传递给C++,然后基于OpenCV Mat函数重新构建一个Mat对象即可,反之亦然。


基本数据类型传递

针对常见的基础数据类型,C#跟C++中基本是关键字一一对应的关系,直接参数传递即可,举例如下。

C++中的接口定义(求两个数之和)
extern "C" __declspec(dllexport) int __stdcall addData(int a, int b);
C#中的导出接口定义
[DllImport("your_test_name.dll")]static extern int addData(int a, int b);
这样就实现了各种基本数据类型的传递。

结构体数据传递
C++中的结构体与接口定义如下
struct MyStruct {  int age = 23;  bool gender=false;};

对应的结构体调用导出接口

extern "C" __declspec(dllexport) void __stdcall getYourStructInfos(MyStruct* infos);
C#定义的结构体与对应的接口声明
struct MyStruct {  public int age;  public bool gender;};
对应的C#导出接口
[DllImport("your_test_name.dll")]static extern void getYourStructInfos([In, Out] MyStruct[] infos);
传递结构体数据必须在C++跟C#两边同时定义相关的结构体数据,然后在C#中以结构体数组方法传递到C++,C++一侧以结构体指针方式接受,并完成数据回填以后,返回数据给C#的对应方法。此外C#定义结构体数组必须指定数组长度,结构体内的INTPtr指针必须在C#一侧完成初始化之后传递到C++中,否则必然导致程序偶发崩溃与宕机。


OpenCV算子工作流引擎

OpenCV工作流引擎SDK支持的零代码功能包含找点、找线、找圆、找边、找线段、找Blob、模板匹配、卡尺测量、轮廓分析、图像预处理、特征匹配、色块查找、九点标定、读码、有无检测、深度学习模型推理等。这些功能都已经实现了C++与C#支持的接口调用,极大幅度降低OpenCV开发难度同时提升OpenCV开发与项目交付速度。

下载与使用OpenCV实验大师工具软与OpenCV工作流引擎SDK请参考下面的链接:
https://appetjpz4tj8166.h5.xiaoeknow.com/p/course/ecourse/course_2XtK2sEi7HNUwt2WscP6tFwxpIb


OpenCV4系统化学习


深度学习系统化学习

推荐阅读

OpenCV4.8+YOLOv8对象检测C++推理演示

ZXING+OpenCV打造开源条码检测应用

攻略 | 学习深度学习只需要三个月的好方法

三行代码实现 TensorRT8.6 C++ 深度学习模型部署

实战 | YOLOv8+OpenCV 实现DM码定位检测与解析

对象检测边界框损失 – 从IOU到ProbIOU

初学者必看 | 学习深度学习的五个误区


OpenCV学堂
三本书《Java数字图像处理-编程技巧与应用实践》、《OpenCV Android开发实战》、《OpenCV4应用开发-入门、进阶与工程化实践》作者。OpenCV实验大师平台 软件作者,OpenCV开发专家、OpenCV研习社创始人。
 最新文章