往往一个项目,算法是用C++写的,而界面需要用C#的Winform去编写,这个时候C#界面需要去调用C++类里面的函数,因为C#和C++是两种不同的语言,两者之间不能直接调用,所以他们之间需要一个桥梁,而托管C++可以充当这个桥梁
项目代码链接:
链接:https://pan.baidu.com/s/1VGkQZjygyc6K_hTR3upugg
提取码:5678
具体实现过程如下:
看看第三方库文件是如何创建出来的
// NativeCppDll.h
#pragma once
#ifndef LX_DLL_CLASS_EXPORTS
#define LX_DLL_CLASS __declspec(dllexport)
#else
#define LX_DLL_CLASS __declspec(dllimport)
#endif
class LX_DLL_CLASS CPerson
{
public:
CPerson();
CPerson(const wchar_t* pName, const wchar_t cSex, int iAge);
void SetName(const wchar_t* pName);
wchar_t* GetName();
void SetSex(const wchar_t cSex);
wchar_t GetSex();
void SetAge(int iAge);
int GetAge();
wchar_t* GetLastError();
private:
wchar_t m_szName[128];
wchar_t m_cSex;
int m_iAge;
wchar_t m_szLastError[128];
void ShowError();
};
// NativeCppDll.cpp
#include "NativeCppDll.h"
#include
#include
using namespace std;
CPerson::CPerson()
{
wcscpy_s(m_szName, _T("No Name"));
m_cSex = 'N';
m_iAge = 0;
wcscpy_s(m_szLastError, _T("No Error"));
}
CPerson::CPerson(const wchar_t* pName, const wchar_t cSex, int iAge)
{
wcscpy_s(m_szLastError, _T("No Error"));
SetName(pName);
SetSex(cSex);
SetAge(iAge);
}
void CPerson::SetName(const wchar_t* pName)
{
if ((pName == NULL) || (wcslen(pName) == 0) || (wcslen(pName) > 127))
{
wcscpy_s(m_szName, _T("No Name"));
wcscpy_s(m_szLastError, _T("The length of the input name is out of range."));
ShowError();
return;
}
wcscpy_s(m_szName, pName);
}
wchar_t* CPerson::GetName()
{
return m_szName;
}
void CPerson::SetSex(const wchar_t cSex)
{
if ((cSex != 'F') && (cSex != 'M') && (cSex != 'm') && (cSex != 'f'))
{
m_cSex = 'N';
wcscpy_s(m_szLastError, _T("The input sex is out of [F/M]."));
ShowError();
return;
}
m_cSex = cSex;
}
wchar_t CPerson::GetSex()
{
return m_cSex;
}
void CPerson::SetAge(int iAge)
{
if ((iAge < 0) || (iAge > 150))
{
m_iAge = 0;
wcscpy_s(m_szLastError, _T("The input age is out of range."));
ShowError();
return;
}
m_iAge = iAge;
}
int CPerson::GetAge()
{
return m_iAge;
}
wchar_t* CPerson::GetLastError()
{
return m_szLastError;
}
void CPerson::ShowError()
{
cerr << m_szLastError << endl;
}
在对第一步的C++类进行暴露的时候,只需要将共有的类成员暴露就行
// ManageCppDll.h
#pragma once
#define LX_DLL_CLASS_EXPORTS
#include "NativeCppDll.h"
#pragma comment(lib,"CDll1.lib")
using namespace System;
namespace ManageCppDll
{
public ref class Person
{
// 包装所有类CPerson的公有成员函数
public:
Person();
Person(String^ strName, Char cSex, int iAge);
~Person();
property String^ Name
{
void set(String^ strName);
String^ get();
}
property Char Sex
{
void set(Char cSex);
Char get();
}
property int Age
{
void set(int iAge);
int get();
}
String^ GetLastError();
private:
// 类CPerson的指针,用来调用类CPerson的成员函数
CPerson* m_pImp;
};
};
// ManageCppDll.cpp
#include "ManageCppDll.h"
#include
namespace ManageCppDll
{
// 在构造函数中创建类CPerson的对象并在析构函数中将该对象销毁
// 所有的成员函数实现都是通过指针m_pImp调用类CPerson的相应成员函数实现
Person::Person()
{
m_pImp = new CPerson();
}
Person::Person(String^ strName, Char cSex, int iAge)
{
// 将string转换成C++能识别的指针
pin_ptr wcName = PtrToStringChars(strName);
m_pImp = new CPerson(wcName, cSex, iAge);
}
Person::~Person()
{
// 在析构函数中删除CPerson对象
delete m_pImp;
}
void Person::Name::set(String^ strName)
{
pin_ptr wcName = PtrToStringChars(strName);
m_pImp->SetName(wcName);
}
String^ Person::Name::get()
{
return gcnew String(m_pImp->GetName());
}
void Person::Sex::set(Char cSex)
{
m_pImp->SetSex(cSex);
}
Char Person::Sex::get()
{
return m_pImp->GetSex();
}
void Person::Age::set(int iAge)
{
m_pImp->SetAge(iAge);
}
int Person::Age::get()
{
return m_pImp->GetAge();
}
String^ Person::GetLastError()
{
return gcnew String(m_pImp->GetLastError());
}
};
(例如:E:\vs2022Code\Dlltest\CDLL2\x64\Debug)
我就暂且放在这里了
告诉编译器
点击生成后,会在类似这个文件夹下 E:\vs2022Code\Dlltest\CDLL2\x64\Debug
将其粘贴到输出目录下,与exe同级
添加依赖项,右击项目依赖项,添加对CDLL2.dll的引用
using ManageCppDll;
Person person = new Person();
person.Name = "StarLee";
person.Sex = 'M';
person.Age = 28;
项目中添加,如下结构
//这段代码不要复制,没有用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using ManageCppDll;
namespace WinFormsApp4
{
internal static class Program
{
///
/// The main entry point for the application.
///
///
[STAThread]
static void Main()
{
Person person = new Person();
person.Name = "StarLee";
person.Sex = 'M';
person.Age = 28;
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}