程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> c#與c++交互的一些東西,

c#與c++交互的一些東西,

編輯:C#入門知識

c#與c++交互的一些東西,


最近做一個項目,對方公司只提供了一個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下面。

 

如果有更好的辦法,請告訴小弟。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved