C#调用C++ DLL类方法

    C++的优势在于高效灵活,C#的优势在于简单易用,两者结合起来对项目开发来说是件好事,而且C++不容易反编译,也保障了代码的安全性,如果一些核心算法使用C#编写,那么保密就是一个问题。

    C++生成的DLL一般只提供函数接口,不能直接用C#调用C++写的类,这样非常不方便,于是经过半天的反复测试,终于确定了一套可行的方案,下面就是整个流程的一个范例。


(1)编写C++类Mask,类前面的extern "C" class _declspec(dllexport)这么一串修饰符是必备的,不然无法导出类。

//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++进行参数的传递是很难弄的一步。

//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环境,使用指针没那么方便了。

//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导出的类。

// 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自带的函数。

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数组,对数组赋值后,将指针传递给类函数。

//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++写的类了,如果觉得有用,不要忘了给我留言啊!!O(∩_∩ )O~
  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值