Unity C#调用RPLidar的C++动态库(.dll)文件(2)

目录

 

前言

创建SDK的静态库

创建DLL动态库

配置RPLidarDLL的属性(配置Release 平台x64)

开始编写动态库雷达管理类代码

定义 DLL 应用程序的导出函数

结语


前言

在上一篇我们已经了解了思岚SDK的数据采集流程

接下来,开始创建动态库, let's go!


创建SDK的静态库

创建静态库,工程命名为rplidar_driver

移除不必要的筛选器

添加新的筛选器,并重命名为SDK

打开工程文件夹,把无用的.h和.cpp删除,并新建SDK文件夹

把SDK里面的include和scr,复制到工程的sdk目录下

手动添加include筛选器,把sdk/include文件添加进来

手动添加src、src/hal、src/arch/win32筛选器,把文件添加进来,sdk的src/arch包含linux、macOS、win32,我们这里只需要win32

这里是工程文件夹include和src的相对路径

接下来可以开始编译了

如果遇到 无法将参数 1 从“const char *”转换为“LPCWSTR”    

选择项目->属性->常规->字符集(选择多字节就ok) 

按着截图配置,SDK的静态库配置就算完成


创建DLL动态库

选中解决方案->添加->新建项目->RPLidarDLL

RPLidarDLL目录放在rplidar_driver工程下

添加rplidar_driver项目的引用,结构如上图所示

配置RPLidarDLL的属性(配置Release 平台x64)

..\..\是上一级的上一级的目录

开始编写动态库雷达管理类代码

新建RPLidarManager.h和RPLidarManager.cpp

#pragma once
#include <rplidar.h>

using namespace rp::standalone::rplidar;

struct LidarData
{
	float angle_z_q14;
	float distant;
	int quality;
};

class RPLidarManager
{
public:
	RPLidarManager();
	~RPLidarManager();

public:
	RPlidarDriver* lidar_drv;
	bool m_isConnected = false;
	rplidar_response_device_info_t devinfo;

	bool m_onMotor = false;
	bool m_onScan = false;

	int onConnect(const char* opt_com_path, int opt_com_baudrate);
	bool onDisconnect();

	bool startMotor();

	bool startScan();
	bool startScanExpress(bool forcescan, int usingScanMode_);


	bool endMotor();
	bool endScan();

	bool releaseDrv();

	int grabData(LidarData* ptr);

	rplidar_response_measurement_node_hq_t buffer[8192];

};

#include "pch.h"
#include "RPLidarManager.h"

RPLidarManager::RPLidarManager()
{
}

RPLidarManager::~RPLidarManager()
{
	onDisconnect();
	releaseDrv();
}

int RPLidarManager::onConnect(const char* opt_com_path, int opt_com_baudrate)
{
	if (m_isConnected) return 0;
	if (lidar_drv == nullptr) {
		lidar_drv = RPlidarDriver::CreateDriver(DRIVER_TYPE_SERIALPORT);

		printf("lidar_drv created");
	}

	if (lidar_drv == nullptr) {
		return -20;
	}


	if (IS_FAIL(lidar_drv->connect(opt_com_path, opt_com_baudrate))) {
		return -21;
	}

	u_result ans = lidar_drv->getDeviceInfo(devinfo);

	if (IS_FAIL(ans)) {
		return ans;
	}

	m_isConnected = true;

	return 0;
}

bool RPLidarManager::onDisconnect()
{
	endScan();
	endMotor();

	if (m_isConnected) {
		if (lidar_drv != nullptr) {
			lidar_drv->stop();
			printf("lidar_drv is stop.");
			m_isConnected = false;
			return true;

		}
		else {
			printf("lidar_drv is null.");
		}
	}
	return false;
}

bool RPLidarManager::startMotor()
{
	if (!m_isConnected) return false;
	if (m_onMotor) return true;

	lidar_drv->startMotor();
	m_onMotor = true;

	return true;
}

bool RPLidarManager::startScan()
{
	if (!m_isConnected) return false;
	if (!m_onMotor) return false;
	if (m_onScan) return true;

	lidar_drv->startScan(0, 1);
	m_onScan = true;
	return true;
}

bool RPLidarManager::startScanExpress(bool forcescan, int usingScanMode_)
{
	if (!m_isConnected) return false;
	if (!m_onMotor) return false;
	if (m_onScan) return true;

	lidar_drv->startScanExpress(forcescan, usingScanMode_);
	m_onScan = true;
	return true;
}

bool RPLidarManager::endMotor()
{
	if (!m_isConnected) return false;
	if (!m_onMotor) return true;
	if (m_onScan) {
		endScan();
	}
	if (m_onScan) return false;

	lidar_drv->stopMotor();
	printf("lidar_drv stop motor");
	m_onMotor = false;

	return true;
}

bool RPLidarManager::endScan()
{
	if (!m_isConnected) return false;
	if (!m_onScan) return true;
	lidar_drv->stop();
	printf("lidar_drv stop scan");
	m_onScan = false;

	return true;
}

bool RPLidarManager::releaseDrv()
{
	if (lidar_drv != nullptr) {

		lidar_drv->DisposeDriver(lidar_drv);
		lidar_drv = nullptr;

		printf("lidar_drv release driver.");

		return true;
	}

	return true;
}

int RPLidarManager::grabData(LidarData* ptr)
{
	if (!m_onScan) {
		return false;
	}
	size_t count = _countof(buffer);
	u_result op_result = lidar_drv->grabScanDataHq(buffer, count);
	if (IS_OK(op_result)) {
		for (int pos = 0; pos < (int)count; ++pos) {
			ptr[pos].angle_z_q14 = buffer[pos].angle_z_q14 * 90.f / 16384.f;
			ptr[pos].distant = buffer[pos].dist_mm_q2 / 4.0f;
			ptr[pos].quality = buffer[pos].quality;
		}
		return count;
	}

	return 0;
}

定义 DLL 应用程序的导出函数

首先介绍下__declspec(dllexport)

__declspec是Microsoft VC中专用的关键字,它配合着一些属性可以对标准C/C++进行扩充。

__declspec关键字应该出现在声明的前面。

__declspec(dllexport)用于Windows中的动态库中,声明导出函数、类、对象等供外面调用,省略给出.def文件。即将函数、类等声明为导出函数,供其它程序调用,作为动态库的对外接口函数、类等。

#define _DLLEXPORT __declspec(dllexport)

extern "C" _DLLEXPORT int Add(int a, int b) {
	return a + b;
}

如上代码所示,动态库里面将包含Add的方法

Unity里面调用方法:

[DllImport("RPLidarDLL")]
public static extern int Add(int a, int b);

接下来我们开整导出函数

#include "pch.h"
#include "RPLidarManager.h"

#define _DLLEXPORT __declspec(dllexport)

static RPLidarManager s_lidarMgr;

extern "C" {
	_DLLEXPORT int OnConnect(const char* opt_com_path, int opt_com_baudrate) {
		if (opt_com_path == nullptr) {
			return -30;
		}
		if (opt_com_baudrate <= 0) {
			return -31;
		}
		return s_lidarMgr.onConnect(opt_com_path, opt_com_baudrate);
	}

	_DLLEXPORT bool OnDisconnect() {

		return s_lidarMgr.onDisconnect();
	}


	_DLLEXPORT bool StartMotor() {
		return s_lidarMgr.startMotor();
	}

	_DLLEXPORT bool StartScan() {
		return s_lidarMgr.startScan();
	}

	_DLLEXPORT bool StartScanExpress(bool forcescan, int usingScanMode_) {
		return s_lidarMgr.startScanExpress(forcescan, usingScanMode_);
	}


	_DLLEXPORT bool EndMotor() {
		return s_lidarMgr.endMotor();
	}

	_DLLEXPORT bool EndScan() {
		return s_lidarMgr.endScan();
	}

	_DLLEXPORT bool ReleaseDrive() {
		return s_lidarMgr.releaseDrv();
	}


	_DLLEXPORT int GetLidarDataSize() {
		return sizeof(LidarData);
	}

	_DLLEXPORT int GrabData(LidarData* data) {
		return s_lidarMgr.grabData(data);
	}

}

把RPLidarDLL设置为启动项,开始编译

编译成功会在rplidar_driver\x64\Release生成RPLidarDLL.dll文件

结语

这篇博文带大家把SDK成功的集成到了动态库里面,并且编写了Unity可以调用的外部函数

资源下载

下一篇带大家进入到Unity中,如何去使用这个动态库文件

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要将C++代码打包给Unity调用,可以通过以下步骤: 1. 创建一个C++库项目,并将其编译为DLL文件。 2. 在Unity中创建一个C#脚本,使用DllImport特性引用DLL文件中的函数。 3. 在C#脚本中调用DLL函数。 下面是一个简单的示例: 1. 创建C++库项目,并将其编译为DLL文件。 首先,创建一个C++库项目并实现一些函数。例如,下面是一个简单的Add函数,它将两个整数相加并返回结果: ``` // MyMathLib.h #ifdef MYMATHLIB_EXPORTS #define MYMATHLIB_API __declspec(dllexport) #else #define MYMATHLIB_API __declspec(dllimport) #endif extern "C" MYMATHLIB_API int Add(int a, int b); ``` ``` // MyMathLib.cpp #include "MyMathLib.h" int Add(int a, int b) { return a + b; } ``` 在这里,我们使用了`__declspec(dllexport)`和`__declspec(dllimport)`来指示编译器导出和导入DLL函数。`MYMATHLIB_API`宏用于将函数标记为导出或导入。 2. 在Unity中创建一个C#脚本,使用DllImport特性引用DLL文件中的函数。 在Unity中,我们可以创建一个C#脚本,并使用DllImport特性来引用DLL文件中的函数。例如,下面是一个简单的例子: ``` // MyMathLib.cs using System.Runtime.InteropServices; public static class MyMathLib { [DllImport("MyMathLib.dll")] public static extern int Add(int a, int b); } ``` 在这里,我们使用DllImport特性来引用DLL文件中的Add函数。`"MyMathLib.dll"`是DLL文件的名称。 3. 在C#脚本中调用DLL函数。 现在,我们可以在C#脚本中调用DLL函数。例如,下面是一个简单的测试: ``` // Test.cs using UnityEngine; public class Test : MonoBehaviour { void Start() { int result = MyMathLib.Add(2, 3); Debug.Log("Result: " + result); // Output: Result: 5 } } ``` 在这里,我们使用`MyMathLib.Add`来调用DLL文件中的Add函数,并将结果打印到Unity控制台中。 这就是将C++代码打包给Unity调用的基本步骤。当然,具体实现可能因项目而异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerrt-J

希望我创作能给你带来有用的帮助

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值