目录
前言
创建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中,如何去使用这个动态库文件