引子
最近一直在搞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 << "Destroy 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
END
作者:gloomyfish
来源:OpenCV学堂
推荐阅读
- 【翻译】在FSDP2中开启Float8 All-Gather
- 上海AI实验室推出DocLayout-YOLO: 速度精度绝佳的文档布局分析模型
- 【ml-engineering 翻译系列】AI系统中的网络概述
- 利用知识蒸馏算法优化 YOLOv5 目标检测 !
欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区嵌入式AI专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。