最近做一个项目,对方公司只提供了一个c++的DLL,但没封住,c#无法DllImport.所以只能自己写c++来封住了。

对方的Dll只接收yuv420的图片格式,所以在c++里用opencv来转换。本来想C#来写,但总觉得麻烦。

【C#】代码

public void Do(Bitmap bp)

{ 

Bitmap outIMG = new Bitmap(bp.Width,bp.Height);

System.Drawing.Imaging.BitmapData bmpData = bp.LockBits(new System.Drawing.Rectangle(0, 0, bp.Width, bp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite,
bp.PixelFormat);

System.Drawing.Imaging.BitmapData bmpData1 = outIMG .LockBits(new System.Drawing.Rectangle(0, 0, outIMG .Width, outIMG .Height), System.Drawing.Imaging.ImageLockMode.ReadWrite,
outIMG .PixelFormat);
CFunction(bmpData.Scan0, bp.Width, bp.Height, 3, 0,bmpData1.Scan0);
img.UnlockBits(bmpData);

outIMG.UnlockBits(bmpData1 );

}

【C++】代码

extern "C" __declspec(dllexport) void WINAPI CFunction(unsigned char* img,int width,int height,int ch,int format,unsigned char* outImg)
{
  Mat frame(Size(width, height), CV_8UC(ch), img); 

  Mat dest;
  cvtColor(frame, dest, format == 0 ? CV_BGR2YUV_I420 : CV_RGB2YUV_I420);

  第三方Dll(dest);

  Mat rgb;

  cvtColor(dest, rgb, format == 0 ? CV_YUV2BGR_I420 : CV_YUV2RGB_I420);

  memcpy((void*)outImg, (void*)dest.data, rgb.cols * rgb.rows * rgb.channels());
}

这基本实现了c++和c#直接图片的对接。但是这种做法会卡C#的程序,我试过backgroundworker,task,很多种方法,但是c#就是会卡住的。具体原因不太清楚,所以觉得这部分的处理在c++中用线程来做,

做完之后通知c#,因为我需要在第三方DLL来生成四个结果图片。所以定义了结构体。

【C#】

[StructLayout(LayoutKind.Sequential)]
public struct ImageResult
{
public IntPtr First;
public IntPtr Second;
public IntPtr Third;
public IntPtr Forth;
}

【C++】

struct ImgeResult
{
void * FirstIMG;
void* SecondIMG;
void* ThirdIMG;
void* FouthIMG;
};

接着要在c#做定义给C++回调的委托。

【c#】

public delegate void CSCallback(ImageResult ir);

public static CSCallback callback;

callback = CSCallbackFunction;

SetCallback(callback );

public static void CSCallbackFunction(ImageResult tick)
{
  处理c++返回的数据
}

调用c++线程函数

public void Do(Bitmap bp)

{ 

Bitmap outIMG = new Bitmap(bp.Width,bp.Height);

System.Drawing.Imaging.BitmapData bmpData = bp.LockBits(new System.Drawing.Rectangle(0, 0, bp.Width, bp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite,
bp.PixelFormat);

DoImage(bmpData.Scan0, bp.Width, bp.Height, 3, 0,bmpData1.Scan0);
img.UnlockBits(bmpData);

outIMG.UnlockBits(bmpData1 );

}

【c++】

typedef void(__stdcall *CPPCallback)(ImgeResult ir);

CPPCallback myCallback;

extern "C" __declspec(dllexport) void WINAPI SetCallback(CPPCallback callback)
{
myCallback = callback;
}

void  OperateImage(unsigned char* img,int width,int height,int ch,int format)
{
Mat frame(Size(width, height), CV_8UC(ch), img);
Mat dest;
cvtColor(frame, dest, format == 0 ? CV_BGR2YUV_I420 : CV_RGB2YUV_I420);
Mat second;
cvtColor(frame, second, format == 0 ? CV_BGR2YUV_I420 : CV_RGB2YUV_I420);
Mat third;
cvtColor(frame, third, format == 0 ? CV_BGR2YUV_I420 : CV_RGB2YUV_I420);
Mat forth;
cvtColor(frame, forth, format == 0 ? CV_BGR2YUV_I420 : CV_RGB2YUV_I420);
Mat nextFirst;
Mat nextSecond;
Mat nextThird;
Mat nextTForth;
 //第三方库处理图片

cvtColor(dest, nextFirst, format == 0 ? CV_YUV2BGR_I420 : CV_YUV2RGB_I420);
cvtColor(second, nextSecond, format == 0 ? CV_YUV2BGR_I420 : CV_YUV2RGB_I420);
cvtColor(third, nextThird, format == 0 ? CV_YUV2BGR_I420 : CV_YUV2RGB_I420);
cvtColor(forth, nextTForth, format == 0 ? CV_YUV2BGR_I420 : CV_YUV2RGB_I420);
ReleaseBelleFaceEngine();
ir.FirstIMG = (void *)malloc(nextFirst.cols * nextFirst.rows * nextFirst.channels());
ir.SecondIMG = (void *)malloc(nextSecond.cols * nextSecond.rows * nextSecond.channels());
ir.ThirdIMG = (void *)malloc(nextThird.cols * nextThird.rows * nextThird.channels());
ir.FouthIMG = (void *)malloc(nextTForth.cols * nextTForth.rows * nextTForth.channels());
memcpy(ir.FirstIMG, (void*)nextFirst.data, nextFirst.cols * nextFirst.rows * nextFirst.channels());
memcpy(ir.SecondIMG, (void*)nextSecond.data, nextSecond.cols * nextSecond.rows * nextSecond.channels());
memcpy(ir.ThirdIMG, (void*)nextThird.data, nextThird.cols * nextThird.rows * nextThird.channels());
memcpy(ir.FouthIMG, (void*)nextTForth.data, nextTForth.cols * nextTForth.rows * nextTForth.channels());

myCallback(ir);
}

extern "C" __declspec(dllexport) void WINAPI DoImage(unsigned char* img,int width,int height,int ch,int format)
{
std::thread th1(OperateImage, img, width, height,ch,format);
th1.detach();
}

到此不会卡住c#程序。

由于本人第一次用c++,也是一边查,一边写的。

c++写的一些心得.

(1)使用opencv要注意链接库是debug还是release的。

(2)到纯净系统下要安装redist,我的目标机是64位,开发环境是2013,所以要装vs2013redist.

(3)最后要注意将 msvcp120.dll,msvcp120d.dll,msvcr120.dll,msvcr120d.dll,vccorlib120.dll,vccorlib120d.dll放到C:\Windows\SysWOW64目录下,32位的目标机器则放到win32下面。

如果有更好的办法,请告诉小弟。

c#与c++交互的一些东西的更多相关文章

  1. android线程 Handler Message Queue AsyncTask线程模型 线程交互 + 修改Button样式 示例 最终easy整合版

     首先原谅我把文章的标题写的这么长.其实我还嫌弃它短了因为 写不下去了所以我就不写了.因为我实在不知道该怎么定义这篇文章的标题或许应该叫 "乱谈"比较合适. 这样可能还体现了 ...

  2. Android 与H5之间的js交互

    之前项目做过一些Android和Html5之间js交互方面的东西,今天有时间就总结一下: 一.为什么要进行js交互: 为了方便原生开发和Html之间数据传递,在静态页面的情况下可以改变原生开发的页面: ...

  3. python之 《进程之间数据交互和进程池》

    1.进程q 进程呢就相当于一个房子,线程就相当于是房子里面在工作的人,那么一个房子的空间对于房子里面的人来说是共享的, 现在是多进程,也就是说有许多房子,很显然这个房子的空间只属于这个房子,不会属于其 ...

  4. 超越 JSON: Spearal 序列化协议简介

      Spearal 是一个新的开源的序列化协议,这个协议旨在初步替换JSON 将HTML和移动应用连接到Java的后端. Spearal的主要目的是提供一个序列协议,这个协议即使是在端点间传输的复杂的 ...

  5. shiro-简介

    简介: Apache Shiro 是Java的一个安全(权限)框架. Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境. Shiro可以完成:认证 ...

  6. 第一章 Shiro简介——《跟我学Shiro》(转)

    目录贴:跟我学Shiro目录贴 1.1  简介 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可 ...

  7. 关于shiro

    1.1  简介 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Securi ...

  8. 工作流软件是未来web的支柱

    Web 3.0正在敲门,但是开门的人你永远都想不到:工作流软件. 传统上工作流软件是企业级的业务流程管理工具,但现在随着网络互联程度的加深,工作流软件开始呈现出其作为互联网技术的一面. 诚然,社会化媒 ...

  9. Shiro简介

    1.简介 Apache Shiro是一个功能强大且易于使用的Java安全框架,进行身份验证,授权,加密和会话管理,可用于保护任何应用程序 - 从命令行应用程序,移动应用程序到大型的Web应用和企业应用 ...

随机推荐

  1. 【POJ】1056 IMMEDIATE DECODABILITY

    字典树水题. #include <cstdio> #include <cstring> #include <cstdlib> typedef struct Trie ...

  2. 【HDOJ】1422 重温世界杯

    简单题. #include <stdio.h> #define MAXN 100005 int wi[MAXN], li[MAXN]; ]; int main() { int n, tot ...

  3. LINUX6.3下RHCS的安装文档

    LINUX6.3下RHCS的安装及集群的配置文档 环境: 目前要给华为E6000系列的两个刀片安装RHCS,每一块刀片有两个业务网口和一个管理网口,但是看不见不物理网卡,而是连接到刀片自身携带的一个交 ...

  4. bzoj1306

    非常好的一道搜索题首先没有别的好办法就只能搜,基于对称性我只要搜对角线上半部分即可然后有些惯用的剪枝啦什么的,具体见程序然后代码很短,然后TLE了(但好像也有人过了)然后就不知道怎么优化了,看到CLJ ...

  5. unity3d shader之Roberts,Sobel,Canny 三种边缘检测方法

    方法其实都差不多,就是用两个过滤器,分别处理两个分量 Sobel算子 先说Sobel算子 GX为水平过滤器,GY为垂直过滤器,垂直过滤器就是水平过滤器旋转90度.过滤器为3x3的矩阵,将与图像作平面卷 ...

  6. 学习嵌入式Linux有没有一个最佳的顺序(持续更新)

    作为一个嵌入式Linux的初学者,我知道我可能将长期处于初学者阶段,因为我至今仍然没有能够摸索出一条很好的道路让我由初学者进入到更高级阶段.但是我始终没有放弃,本篇文章就是用来记录我学习嵌入式Linu ...

  7. ACM1024动态规划

    #include <cstdio> #include <algorithm> #define FI(a, b, c) for(int a = (b); a <= (c); ...

  8. ubuntu制作usb启动盘

    准备: u盘 iso镜像文件--ubuntu-12.04.2-desktop-amd64.iso 烧盘软件--unetbootin-linux-583 步骤: 格式化u盘 查看u盘信息 #mount/ ...

  9. 《University Calculus》-chape8-无穷序列和无穷级数-基本极限恒等式

    基于基本的极限分析方法(诸多的无穷小以及洛必达法则),我们能够得到推导出一些表面上看不是那么显然的式子,这些极限恒等式往往会在其他的推导过程中用到,其中一个例子就是概率论中的极限定理那部分知识.

  10. Installing scikit-learn

    Installing scikit-learn http://scikit-learn.org/stable/install.html Installing scikit-learn There ar ...