[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。