C++/CLI封装

创建c++/CLI 库

创建过程主要包括三个步骤:核心C++项目,C++/CLI库,以及使用C++/CLI库的c#项目。这种方法用法应用的代表之一:游戏引擎,可以用c#编写脚本,例如Unity3D或者Xenko。但是游戏引擎会在短时间内处理大量数据,用c#编写并不是最好的办法,因此用c++编写核心功能,通过c++/CLI封装一层提供给c#.

  1. 环境配置
    在这里插入图片描述
    如图所示,修改VS安装,选择指示部分即“c++桌面安装”----“C++/CLI support”。
  2. 创建c++核心项目
    打开VS创建新项目,C++项目,选择“空项目”,一般命名为“Core”,主要是核心功能实现,当然可以用其他名称。在这里插入图片描述
    然后设置此项目的相关属性,右击项目----点击“属性”,在常规下选择“配置类型为”----“静态库.lib”,生成静态库,被引用在c++/cli项目中,如图所示
    在这里插入图片描述
    然后在里面添加你的核心功能代码的头文件及源文件,这里添加的例子代码:
//Entity.h
  #pragma once
  namespace Core
  {
  	class Entity
  	{
  	public:
  		const char* m_Name;
  	private:
  		float m_XPos, m_YPos;
  	public:
  		Entity(const char* name, float xPos, float yPos);
  		
  		void Move(float deltaX, float deltaY);
  		inline float GetXPosition() const { return m_XPos; };
  		inline float GetYPosition() const { return m_YPos; };
  	};
  }
//Entity.cpp
  #include "Entity.h"
  #include <iostream>
  namespace Core
  {
  	Entity::Entity(const char* name, float xPos, float yPos)
  		: m_Name(name), m_XPos(xPos), m_YPos(yPos)
  	{
  		std::cout << "Created the Entity object!" << std::endl;
  	}
  	void Entity::Move(float deltaX, float deltaY)
  	{
  		m_XPos += deltaX;
  		m_YPos += deltaY;
  		std::cout << "Moved " << m_Name << " to (" << m_XPos << ", " << m_YPos << ")." << std::endl;
  	}
  }

这里还创建了命名为Core.h的文件,这个文件将被包含在C++/CLI项目中,因为例子中核心项目文件比较少,所以这个文件看起来不是很重要,但当文件比较多时,很有必要

//Core.h
  #pragma once
  #include "Entity.h"
  1. C++/CLI库的创建
    创建C++/CLI库,这里很容易出错,在当前解决方案中新增项目,选择“c++”语言,搜索"crl",选择“CRL空项目(.NET Core)”,如图所示在这里插入图片描述
    项目名称为Wapper,创建完项目之后,添加对核心项目Core的引用,右键项目名称—“属性”—“项目引用”----选择Core,之后转到属性—“C/C++”—“预编译头”,然后将第一个选项更改为“不使用预编译头”。这样就设置好这个库的设置,开始文件的添加:
//ManagedObject.h
  #pragma once
  using namespace System;
  namespace CLI {
  	
  	template<class T>
  	public ref class ManagedObject
  	{
  	protected:
  		T* m_Instance;
  	public:
  		ManagedObject(T* instance)
  			: m_Instance(instance)
  		{
  		}
  		virtual ~ManagedObject()
  		{
  			if (m_Instance != nullptr)
  			{
  				delete m_Instance;
  			}
  		}
  		!ManagedObject()
  		{
  			if (m_Instance != nullptr)
  			{
  				delete m_Instance;
  			}
  		}
  		T* GetInstance()
  		{
  			return m_Instance;
  		}
  	};
  }

ManagedObject将充当我们将在此项目中创建的所有包装器类的超类。它的唯一目的是持有一个指向Core项目中非托管对象的指针。该类包含一个析构函数(〜ManagedObject)(每当您使用delete关键字删除对象时都会调用该析构函数)和一个终结器(!ManagedObject),而该终结器在销毁C++/CLI对象时由垃圾回收器调用。
然后添加Entity.h及Entity.cpp

//Entity.h
  #pragma once
  #include "ManagedObject.h"
  #include "../Core/Core.h"
  using namespace System;
  namespace CLI
  {
  	public ref class Entity : public ManagedObject<Core::Entity>
  	{
  	public:
  		
  		Entity(String^ name, float xPos, float yPos);
  		void Move(float deltaX, float deltaY);
  		property float XPosition
  		{
  		public:
  			float get()
  			{
  				return m_Instance->GetXPosition();
  			}
  		private:
  			void set(float value)
  			{
  			}
  		}
  		property float YPosition
  		{
  		public:
  			float get()
  			{
  				return m_Instance->GetYPosition();
  			}
  		private:
  			void set(float value)
  			{
  			}
  		}
  	};
  }
//Entity.cpp
  #include "Entity.h"
  namespace CLI
  {
  	Entity::Entity(String^ name, float xPos, float yPos)
  		: ManagedObject(new Core::Entity(string_to_char_array(name), xPos, yPos))
  	{
  		Console::WriteLine("Creating a new Entity-wrapper object!");
  	}
  	void Entity::Move(float deltaX, float deltaY)
  	{
  		Console::WriteLine("The Move method from the Wrapper was called!");
  		m_Instance->Move(deltaX, deltaY);
  	}
  }

除了将.NET字符串转换为C ++ const char *之外,您可能还需要将.NET数组转换为C ++数组。即使它们看起来相同,它们之间也有很大的区别:.NET数组是对象,而C ++数组只是指向第一个元素的指针。

using namespace System::Runtime::InteropServices;
  static const char* string_to_char_array(String^ string)
  	{
  		const char* str = (const char*)(Marshal::StringToHGlobalAnsi(string)).ToPointer();
  		return str;
  	}
static void int_array_conversion(array<int>^ data)
  {
  		pin_ptr<unsigned int> arrayPin = &data[0];
  		unsigned int size = data->Length;	
  }
  1. 创建C#项目使用以上C++/CLI库
    在此解决方案中再添加一个C#项目,并测试我们是否能够访问C ++功能。右键单击该解决方案,然后添加一个新的C#控制台应用程序;名称为“SandBox”。
    在这里插入图片描述
    然后与之前同样的方法,将Wrapper项目引用添加至SandBox中。测试代码:
using System;
  using CLI;
  namespace Sandbox
  {
      class Program
      {
          static void Main(string[] args)
          {
              Entity e = new Entity("The Wallman", 20, 35);
              e.Move(5, -10);
              Console.WriteLine(e.XPosition + " " + e.YPosition);   
              Console.Read();        
   }
      }
  }

这样就完成了,让我们看看结果吧,yeah!成功了,赶快创建你的项目吧
在这里插入图片描述

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的示例,演示如何在 C++/CLI封装 VB.NET DLL 中的 API: 1. 在 VB.NET 中创建一个 DLL 文件 首先,在 VB.NET 中创建一个名为 "MyLibrary" 的 Class Library 项目,并在其中添加以下代码: ``` Public Class MyAPI Public Function AddNumbers(ByVal num1 As Integer, ByVal num2 As Integer) As Integer Return num1 + num2 End Function End Class ``` 然后,编译该项目并生成 MyLibrary.dll 文件。 2. 在 C++/CLI 中添加对 VB.NET DLL 的引用 打开一个 C++/CLI 项目,并在其中添加对 MyLibrary.dll 的引用。具体步骤如下: - 在 "解决方案资源管理器" 中,右键单击 "引用",选择 "添加引用"。 - 在 "添加引用" 窗口中,点击 "浏览" 按钮,并选择 MyLibrary.dll 文件。 - 点击 "确定",完成添加引用的操作。 3. 在 C++/CLI 中创建 public ref class 在 C++/CLI 中创建一个名为 "MyWrapper" 的 public ref class,用于封装 MyLibrary.dll 中的 API。具体代码如下: ``` #include "stdafx.h" #include <msclr\auto_gcroot.h> using namespace System; using namespace MyLibrary; public ref class MyWrapper { public: MyWrapper() { // 初始化 VB.NET API 对象 m_api = gcnew MyAPI(); } int AddNumbers(int num1, int num2) { // 调用 VB.NET API 的 AddNumbers 方法 return m_api->AddNumbers(num1, num2); } private: // 使用 auto_gcroot 包装 VB.NET API 对象 msclr::auto_gcroot<MyAPI^> m_api; }; ``` 需要注意的是,这里使用了 "msclr\auto_gcroot.h" 头文件,以便在 C++/CLI包装 VB.NET 对象。 4. 编译并使用封装的 API 将 MyWrapper 编译为 DLL 文件后,即可在其他应用程序中使用该 DLL 文件,并调用其中的 AddNumbers 方法,例如: ``` #include <iostream> #include "MyWrapper.h" using namespace std; int main() { MyWrapper^ wrapper = gcnew MyWrapper(); int result = wrapper->AddNumbers(1, 2); cout << "The result is: " << result << endl; return 0; } ``` 运行该应用程序后,将输出 "The result is: 3"。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值