目录

 

前言

创建SDK的静态库

创建DLL动态库

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

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

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

结语


前言

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

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


创建SDK的静态库

unity 日历表插件_导出函数

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

unity 日历表插件_导出函数_02

移除不必要的筛选器

unity 日历表插件_动态库_03

unity 日历表插件_动态库_04

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

unity 日历表插件_动态库_05

unity 日历表插件_导出函数_06

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

unity 日历表插件_unity 日历表插件_07

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

unity 日历表插件_导出函数_08

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

unity 日历表插件_#include_09

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

unity 日历表插件_导出函数_10

unity 日历表插件_动态库_11

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

unity 日历表插件_unity 日历表插件_12

unity 日历表插件_unity 日历表插件_13

unity 日历表插件_unity 日历表插件_14

unity 日历表插件_c++_15

接下来可以开始编译了

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

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

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


创建DLL动态库

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

unity 日历表插件_c++_16

RPLidarDLL目录放在rplidar_driver工程下

unity 日历表插件_动态库_17

unity 日历表插件_#include_18

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

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

unity 日历表插件_导出函数_19

unity 日历表插件_导出函数_20

unity 日历表插件_动态库_21

unity 日历表插件_unity 日历表插件_22

unity 日历表插件_c++_23

unity 日历表插件_c++_24

unity 日历表插件_动态库_25

unity 日历表插件_动态库_26

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

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

新建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中,如何去使用这个动态库文件