• C#调用C++ DLL类方法


    C++的优势在于高效灵活,C#的优势在于简单易用,两者结合起来对项目开发来说是件好事,而且C++不容易反编译,也保障了代码的安全性,如果一些核心算法使用C#编写,那么保密就是一个问题。
        C++生成的DLL一般只提供函数接口,不能直接用C#调用C++写的类,这样非常不方便,于是经过半天的反复测试,终于确定了一套可行的方案,下面就是整个流程的一个范例。
    
    (1)编写C++类Mask,类前面的extern "C" class _declspec(dllexport)这么一串修饰符是必备的,不然无法导出类。
    [cpp] view plain copy print?
    //Mask类头文件mask.h  
    #pragma once  
       
    extern "C" class _declspec(dllexport) Mask  
    {  
    public:  
           Mask(char* inputFile,int* maskValue,int maskLength);  
           virtual void Run(void);  
           ~Mask(void);  
       
    private:  
           char* _inputFile;  
           int* _maskValue;  
           int _maskLength;  
    };  
    
    (2)Mask类内部实现,这里使用char*和int*这两个有代表性的参数,C#向C++进行参数的传递是很难弄的一步。
    [cpp] view plain copy print?
    //Mask类实现文件mask.cpp  
    Mask::Mask(char* inputFile ,int* maskValue,int maskLength)  
    {  
           _inputFile=new char[strlen(inputFile)+1];  
           strcpy(_inputFile,inputFile);  
       
           _maskValue=new int[maskLength];  
           _maskLength=maskLength;  
           for(int i=0;i<maskLength;i++)  
                  _maskValue[i]=maskValue[i];  
    }  
       
    void Mask::Run(void)  
    {  
    }  
       
    Mask::~Mask(void)  
    {  
           if (_inputFile)  
           {  
                  delete [] _inputFile;  
                  _inputFile=NULL;  
           }  
           if (_maskValue)  
           {  
                  delete [] _maskValue;  
                  _maskValue=NULL;  
           }  
    }  
    
    可以设置生成类型为DLL,然后将debug目录下的dll文件和lib文件找到,留待下一步使用。
    
    (3)编写C++.NET类MaskCLR,C++.NET我一直认为就是个摆设,没想到也能派上用场,难得啊,也不完全是个废物。MaskCLR可以调用Mask类,注意函数的参数已经变成String ^和int*,现在是.NET环境,使用指针没那么方便了。
    [cpp] view plain copy print?
    //MaskCLR类头文件,用来包装Mask类MaskCLR.h  
    #pragma once  
    #include " mask.h"        //这个就是上面的Mask头文件  
       
    public ref class MaskCLR  
    {  
    private:  
           char* _inputFile;  
           int* _maskValue;  
           int _maskLength;  
       
    public:  
           MaskCLR(String ^ inputFile,int* maskValue,int maskLength);  
           virtual void  Run(void) override;  
    };  
    
    (4)MaskCLR类内部实现,首先要处理参数类型问题,将String ^类型转为char*。在MaskCLR:: Run函数内部调用Mask类,Mask是DLL导出的类。
    [cpp] view plain copy print?
    // MaskCLR类内部实现MaskCLR.cpp  
    #include "MaskCLR.h"  
       
    MaskCLR::MaskCLR(String ^ inputFile,int* maskValue,int maskLength)  
    {  
           _inputFile=GlobeFunction::StringToChar(inputFile);  
           _maskValue=maskValue;  
           _maskLength=maskLength;  
    }  
       
    void MaskCLR:: Run(void)  
    {  
           Mask mask(_inputFile, _maskValue,_maskLength);  
           mask.Run();                    
    }  
    
    (5)将String ^类型转为char*,可以利用StringToHGlobalAnsi这个.NET自带的函数。
    [csharp] view plain copy print?
    char* GlobeFunction::StringToChar(String ^str)  
    {  
           return (char*)(Marshal::StringToHGlobalAnsi(str)).ToPointer();  
    }  
    
    (6)最终生成了两个DLL文件,一个是原始C++编写的,另一个是托管C++编写的,托管dll只是个外壳,最终还是调用原始dll,因此这两个dll要放在一起。下面终于进入C#环境了,首先将托管dll添加引用到C#工程中,C++.NET和C#可以直接互用。
     
    (7)由于有个int*类型参数,在C#里指针属于不安全代码,因此使用unsafe关键字将涉及到指针的代码包括起来,在工程属性里设置允许使用不安全代码。定义int指针需要使用stackalloc关键字,创建一个int数组,对数组赋值后,将指针传递给类函数。
    [csharp] view plain copy print?
    //c#调用托管dll中的MaskCLR类form1.cs  
    unsafe  
    {  
           int* value = stackalloc int[1];  
           value[0] = 0;  
           MaskCLR mask = new MaskCLR("D:\临时\mask8.tif", value, 1);  
           mask.Run();  
    }  
    
    (8)至此大功告成,可以用C#很方便的调用C++写的类了.
  • 相关阅读:
    在家赚钱,威客网站的使用方法
    帅哥编年史
    有些话不吐不快,事情不是这样做滴
    面向对象与形而上学
    Asp.net Mvc问题索引
    Asp.net Mvc视频教程 页面传值基础(get/post/UpdateModel)
    Asp.net Mvc 入门视频教程(试水)
    Linq to Entities in Ado.net EF的事务
    Json.net/Newtonsoft 3.0 新特性JObject/Linq to Json
    Entity SQL Language六 数字函数、时间函数及其它
  • 原文地址:https://www.cnblogs.com/profession/p/5851749.html
Copyright © 2020-2023  润新知