上一篇(一个传感器的SDK(C++) – Zla (fromzla.cn))介绍了一个传感器SDK C++部分,但是C++的库就项目使用而言不太够用,有些项目开发也会使用C#实施,C#调用C++可以使用DllImport
或者编一个CLR项目,这里做一个CLR的封装
创建一个CLR项目(关于CLI项目,参考:使用 C++/CLI 进行 .NET 编程 | Microsoft Learn)
SensorSDKDotNet.h
#pragma once //C++ SDK的头文件 #include "../SharedLibs/SensorSDK/include/sensor_api.h" using namespace System; namespace sensor_sdk_dot_net { public delegate void SensorDataCallback(int data); public delegate void SensorLogCallback(String^ log_str); public ref class sensor_sdk sealed { private: void* sensor_; public: sensor_sdk(); ~sensor_sdk(); bool open(); bool close(); bool execute_cmd(String^ cmd_str); int get_int_value(String^ param_name); bool set_int_value(String^ param_name, int value); bool register_data_callback(SensorDataCallback^ data_callback); bool register_log_callback(SensorLogCallback^ log_callback); }; }
SensorSDKDotNet.cpp
#include "SensorSDKDotNet.h" using namespace Runtime::InteropServices; sensor_sdk_dot_net::sensor_sdk::sensor_sdk() { const pin_ptr<void*> handle = &this->sensor_; const auto is_succeed = sensor_create(handle); if (!is_succeed) throw gcnew ApplicationException("Instantiation sensor sdk fail!"); } sensor_sdk_dot_net::sensor_sdk::~sensor_sdk() { sensor_destroy(sensor_); } bool sensor_sdk_dot_net::sensor_sdk::open() { return sensor_open(sensor_); } bool sensor_sdk_dot_net::sensor_sdk::close() { return sensor_close(sensor_); } bool sensor_sdk_dot_net::sensor_sdk::execute_cmd(String^ cmd_str) { const auto cmd = static_cast<char*>(safe_cast<void*>(Marshal::StringToHGlobalAnsi(cmd_str))); const auto is_succeed = sensor_execute_cmd(sensor_, cmd); Marshal::FreeHGlobal(IntPtr(cmd)); return is_succeed; } int sensor_sdk_dot_net::sensor_sdk::get_int_value(String^ param_name) { const auto name = static_cast<char*>(safe_cast<void*>(Marshal::StringToHGlobalAnsi(param_name))); int value = -1; const auto is_succeed = sensor_get_int_value(sensor_, name, &value); Marshal::FreeHGlobal(IntPtr(name)); return value; } bool sensor_sdk_dot_net::sensor_sdk::set_int_value(String^ param_name, const int value) { const auto name = static_cast<char*>(safe_cast<void*>(Marshal::StringToHGlobalAnsi(param_name))); const auto is_succeed = sensor_set_int_value(sensor_, name, value); Marshal::FreeHGlobal(IntPtr(name)); return is_succeed; } void _stdcall sensor_data_callback_func(const int data, void* p_user) { auto callback = Marshal::GetDelegateForFunctionPointer<sensor_sdk_dot_net::SensorDataCallback^>(IntPtr(p_user)); callback(data); } void _stdcall sensor_log_callback_func(char* sensor_log, void* p_user) { auto callback = Marshal::GetDelegateForFunctionPointer<sensor_sdk_dot_net::SensorLogCallback^>(IntPtr(p_user)); callback(Marshal::PtrToStringAnsi(IntPtr(sensor_log))); } bool sensor_sdk_dot_net::sensor_sdk::register_data_callback(SensorDataCallback^ data_callback) { IntPtr callback_func = Marshal::GetFunctionPointerForDelegate(data_callback); const auto is_succeed = sensor_register_data_callback(sensor_, sensor_data_callback_func, callback_func.ToPointer()); return is_succeed; } bool sensor_sdk_dot_net::sensor_sdk::register_log_callback(SensorLogCallback^ log_callback) { IntPtr callback_func = Marshal::GetFunctionPointerForDelegate(log_callback); const auto is_succeed = sensor_register_log_callback(sensor_, sensor_log_callback_func, callback_func.ToPointer()); return is_succeed; }
创建一个C#控制台项目进行测试,此处运行时要注意运行目录要包含c++库的dll和clr库的dll
Program.cs
using System; using sensor_sdk_dot_net; namespace CSDemo { internal class Program { private static void Main(string[] args) { var sensor = new sensor_sdk(); sensor.register_data_callback(data => { Console.WriteLine($"传感器数据:{data}"); }); sensor.register_log_callback(log => { Console.WriteLine($"传感器日志:{log}"); }); Console.WriteLine("q - 退出"); Console.WriteLine("open - 打开传感器"); Console.WriteLine("close - 关闭传感器"); Console.WriteLine("cmd - 执行命令(当前支持 collect 命令)"); Console.WriteLine("read - 读参数"); Console.WriteLine("write - 写参数"); Console.Write("键入指令:"); var cmd = Console.ReadLine(); while (true) { if (cmd is "q") break; switch (cmd) { case "open": sensor.open(); break; case "close": sensor.close(); break; case "cmd": Console.Write("命令:"); cmd = Console.ReadLine(); sensor.execute_cmd(cmd); break; case "read": Console.Write("输入参数名:"); var readParamName = Console.ReadLine(); var readValue = sensor.get_int_value(readParamName); Console.WriteLine($"Get param {readParamName} value is {readValue}"); break; case "write": Console.Write("输入参数名:"); var writeParamName = Console.ReadLine(); Console.Write("输入参数值:"); var writeStr = Console.ReadLine(); var isValid = int.TryParse(writeStr, out var writeValue); if (!isValid) Console.WriteLine("Input is invalid"); sensor.set_int_value(writeParamName, writeValue); Console.WriteLine($"Get param {writeParamName} value is {writeValue}"); break; } Console.Write("键入指令:"); cmd = Console.ReadLine(); } } } }