已得结论
在前面的文章《C++/CLI基本语法和最佳实践》中,已经得到了以下重要结论:
(1)托管类型(value struct / value class 和 ref struct / ref class)
- 不能定义非托管类型的字段。
- 可以定义非托管类型的C++普通指针类型。
- 可以使用C++的基本数据类型,因为在这些类型可以和C#数据类型自动转换。
- 托管类型的方法参数和返回值可以为非托管类型,但是无法传参。
(2)封装程序库供C#使用:
- 凡是要暴露给C#项目的接口,统一使用托管类型。
- 托管类型的指针成员变量、参数或返回值为非托管类型的方法,只能充当函数逻辑实现的辅助,无法暴露给C#项目(避免出错,最好不要使用!)
- 封装原生C++代码给C#项目使用:可以定义一个C++类指针成员变量,作为原生C++代码的统一访问入口;(推荐方法)
- 封装原生C++代码给C#项目使用:可在C++/CLI的方法内部使用原生C++代码中的静态方法,或实例化原生C++代码里面的类,从而使用既有原生C++的代码。
下面以一个完整实例详细介绍如何使用C++/CLI封装原生C++库供.NET项目调用。
制作原生C++库
这里使用动态链接库,设置预编译器定义MYDLL_EXPORTS,确保预编译阶段MYDLL_EXPORTS宏被替换为__declspec(dllexport)。
头文件
#pragma once
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
#include <vector>
#include <string>
class MYDLL_API MyComputer
{
public:
double Add(double a, double b);
bool Divide(double a, double b, double& res);
double Sum(const std::vector<double>& data);
bool IsStringRight(std::string text);
};
注意:MYDLL_API必须放在class关键字后面,易错!
源文件
#include "MyComputer.h"
double MyComputer::Add(double a, double b)
{
return a + b;
}
bool MyComputer::Divide(double a, double b, double& res)
{
if (b == 0