[C++] 使用C++编写dll,并用C#调用dll

2018-06-14  本文已影响0人  Erland

最近心血来潮,和一个朋友打算一起写一个放假查询应用软件。
我负责编写假期识别算法,对方负责界面设计,交互设计,以及上层API获取等。对方使用C#语言进行桌面应用开发,也是我们使用的主语言,但我更熟悉C++,因此我们商定:由我负责使用C++编写动态链接库(dll)给上层的C#提供接口

DLL文件创建和编译

IDE:Visual Studio 2015
新建项目:选择 Visual C++、Win32、Win32项目,确定。

新建项目
选择DLL,这里尽量不要使用空项目,IDE会自动生成几个文件。
创建DLL
自动生成的文件包括:stdafx.h、targetver.h、dllmain.cpp、stdafx.cpp、以及ReadMe.txt。具体可以打开查看文件注释,我们只需要在此基础上添加自己的代码。
类的设计
头文件示例如下:
class __declspec(dllexport) StatusDay
{
public:
  static const int ILLEGAL = -1;      // illegal
  StatusDay();
  StatusDay(int status);
  ~StatusDay();
  void setstatus(int new_status);
  int getstatus();
private:
  int status;
  // 0 work day
  // 1 work but holiday
  // 2 holiday: 6, 7
  // 3 holiday: festival
  // 4 holiday: summer, winter
};

__declspec(dllexport):说明这个类是个导出类,从本DLL文件导出。
源文件示例如下:

StatusDay::StatusDay()
{
  setstatus(0);
}

StatusDay::StatusDay(int status)
{
  setstatus(status);  // init the status of this day.
}

void StatusDay::setstatus(int nowstatus)
{
  status = nowstatus;
}

int StatusDay::getstatus()
{
  if (status >= 0 && status <= 4) return status;
  else return ILLEGAL;
}

StatusDay::~StatusDay()
{
}

不再赘述。
为了方便C#的调用,类设计完成之后,还需要把类转换成函数接口,示例如下:

#pragma once
#include "stdafx.h"
namespace LastCalender
{
  extern "C" __declspec(dllexport) void __stdcall init(int now_year);
  extern "C" __declspec(dllexport) void __stdcall read_festival(int month, int day, int is_festival);
  extern "C" __declspec(dllexport) void __stdcall read_vacation(int start_month, int start_day, >int end_month, int end_day, bool is_summer);
  extern "C" __declspec(dllexport) void __stdcall calcu_holiday();
  extern "C" __declspec(dllexport) bool __stdcall seek_status(int month, int day);
  extern "C" __declspec(dllexport) int __stdcall Test();
}
#include "seek.h"
#include "LastCalender.h"

namespace LastCalender
{
  Seek *seek;

  void __stdcall init(int now_year)
  {
      if (now_year > 0)
          seek = new Seek(now_year);
      else
          seek = new Seek();
  }

  void __stdcall read_festival(int month, int day, int is_festival)
  {
      seek->read_festival(month, day, is_festival);
  }

  void __stdcall read_vacation(int start_month, int start_day, int end_month, int end_day, bool is_summer)
  {
      seek->read_vacation(start_month, start_day, end_month, end_day, is_summer);
  }

  void __stdcall calcu_holiday()
  {
      seek->holiday_in_year();
  }

  bool __stdcall seek_status(int month, int day)
  {
      return seek->seek_in_date(month, day);
  }

  int __stdcall Test()
  {
      return seek->for_test();
  }
}

以上将类的成员函数转成 extern "C" __declspec(dllexport) 声明的函数,给外部调用。
到此编译即可生成dll文件。

DLL文件的调用

新建C#项目,将上面生成的dll文件复制到此项目文件夹下。
新建一个类,导入dll文件中的函数

 public class Calender
 {
       [DllImport("LastCalender.dll")]
       public static extern int init(int n);

       [DllImport("LastCalender.dll")]
       public static extern int read_festival(int month, int day, int is_festival);

       [DllImport("LastCalender.dll")]
       public static extern int read_vacation(int start_month, int start_day, int end_month, int end_day, bool is_summer);

       [DllImport("LastCalender.dll")]
       public static extern int calcu_holiday();

       [DllImport("LastCalender.dll")]
       public static extern int seek_status(int month, int day);
}

调用新类中所需函数即可。

特别鸣谢:我的队友,Small Snow。
上一篇 下一篇

猜你喜欢

热点阅读