zoukankan      html  css  js  c++  java
  • 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:WindowsSysWOW64目录下,32位的目标机器则放到win32下面。

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

  • 相关阅读:
    LinkedHashMap、HashMap和TreeMap的比较使用
    RocketMQ之Namesrv
    mysql创建、删除、查看索引
    java8 JVM堆内存(heap) 新生代 老年代 元空间垃圾回收详解
    Java中GCRoots包括哪些
    单例模式双重校验锁
    内存屏障
    LockSupport的用法及原理
    HashSet,TreeSet和LinkedHashSet的区别
    Windows常用网络命令技巧汇总
  • 原文地址:https://www.cnblogs.com/qiurideyun/p/4526946.html
Copyright © 2011-2022 走看看