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

引子

最近一直在搞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学堂

推荐阅读

欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区嵌入式AI专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。

推荐阅读
关注数
18835
内容数
1369
嵌入式端AI,包括AI算法在推理框架Tengine,MNN,NCNN,PaddlePaddle及相关芯片上的实现。欢迎加入微信交流群,微信号:aijishu20(备注:嵌入式)
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息