当前位置: 首页 > ds >正文

opendds编译开发(c#封装)

opendds是对DDS协议的开源实现,具体可以查阅官网。

我使用的是源码编译开发,博文只针对windows平台。

环境准备

环境安装

1.visual studio 2022,我是企业版,安装需要选择c++

2.Per下载安装,下载链接:https://strawberryperl.com/

源码

1.opendds源码

下载发布的版本。

下载:https://github.com/OpenDDS/OpenDDS

2.ACE源码

下载发布版本。看清楚说明,下对版本,我下载的ACE+TAO-8.0.2.zip

下载地址:https://github.com/DOCGroup/ACE_TAO/releases/tag/ACE%2BTAO-8_0_2

配置系统环境

以我的开发环境为例。

解压opendds源码,解压ace源码以后放在一起,也可以不放一起,弄清楚文件夹。

1.配置环境系统变量

ACE_ROOT :ace源码位置

MPC_ROOT :MPC位置,在ACE源码里面的MPC

TAO_ROOT : %ACE_ROOT%\TAO

DDS_ROOT :DDS源码位置

以为我为例分别是:

ACE_ROOT:E:\OpenDDS-3.31.0\ACE_wrappers

DDS_ROOT:E:\OpenDDS-3.31.0

TAO_ROOT:E:\OpenDDS-3.31.0\ACE_wrappers\TAO

MPC_ROOT:E:\OpenDDS-3.31.0\MPC

其中ACE_wrappers就是拷贝的ACE源码

2.Path变量

%ACE_ROOT%\lib
%ACE_ROOT%\bin
%DDS_ROOT%\lib
%DDS_ROOT%\bin

3.其它

如果你还在参考网上其它资料,可能需要添加一些其它路径,

Path变量中添加perl路径,例如:E:\strawberry-perl-5.40.0.1-64bit-portable\perl\bin

Path变量中添加编译器路径,例如:D:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64

生成opendds项目

这部分主要是编译opendds源码,生成依赖库。我推荐博文给大家参考。

Windows下的OpenDDS编译(超详细)-CSDN博客

OPenDDS程序 的 实现+运行-CSDN博客

最主要的官方文档:Building and Installing - OpenDDS 3.31.0

官方文档构建和安装一节。

编译ACE

1.配置修改

进入ACE源码里面,找到ace文件夹,在ace文件下添加文件config.h,输入内容:#include "ace/config-win32.h"。

2.编译

在ACE源码中找到ACE_wrappers_vs2022.sln,编译。

编译opendds

进入opendds源码文件夹,运行“configure.cmd”。双击即可。

正常情况下会生成DDS_no_tests.sln,编译。

所有编译的,都可以用vs2022打开.sln编译,也可以用命令行编译。

正常生成则opendds依赖库有了。

开发项目

这里主要是使用opendds库,opendds作为传输工具,在我们自己的项目中肯定是库,库就需要使用。这里以c#封装使用为例看看项目开发。

读懂官网文档是很重要的,其中“开始”一节演练了项目使用。

这里你需要简单立即idl数据结构定义,可以不管

tao_idl Messenger.idl
opendds_idl Messenger.idl

这部分是介绍idl的使用生成,就是中间件。

项目开始

准备文件

在你平时创建项目的位置,建立一个项目文件夹,名称:DllForOpendds。

在该文件夹下面再建立一个文件夹OpenddsWrappers。

在OpenddsWrappers里面建立2个文件,分别是DDSMessenger.idl,DDS.MPC。

其中DDSMessenger.idl的内容就和官网例子差不多,刚刚开始就一样也可以。

这是我的:


module DDSMessenger{@topicstruct Message {//来源string from;//主题string subject;@key long subject_id;//附属信息string text;//传输内容sequence <octet> content;//域IDlong domain_id;};
@topic
struct Heartbeat
{@key long use_id;long index;
};
};

官网例子里面分离了项目,一个订阅一个发布,这里是为了封装库我就不分开了,DDS.mpc文件就是为了用MPC工具构建项目的文件。里面的内容是:

project(*idl): dcps {// This project ensures the common components get built first.TypeSupport_Files {DDSMessenger.idl}custom_only = 1
}project(*OpenddsWrappers): dcpsexe_with_tcp {exename = OpenddsWrappersafter  += *idlTypeSupport_Files {DDSMessenger.idl}Header_Files {OpenddsExport.hDataReaderListenerImpl.hOpenddsWarp.hPublisher.hSubscriber.hSubscriber.h}Source_Files {DataReaderListenerImpl.cppOpenddsExport.cpp}
}

有了这两个文件,就可以生成VC的项目了,在当前文件下,执行命令:

perl %ACE_ROOT%\MPC\mwc.pl -type vs2022,这样就生成了项目OpenddsWrappers.sln,

用vs2022打开项目,里面就是2个c++项目,当前还没有c#的项目,对DDS_OpenddsWrappers做一点修改。

1.

1.右键DDS_OpenddsWrappers,打开属性,“常规”中修改配置类型为dll

2.继续,“链接器”中输出文件修改文件后缀.dll

如图效果:

生成一下OpenddsWrappers解决方案,就会有一些DDSMessengerTypeSupportC.h等文件产生。

开发功能

1.opendds使用开发

在DDS_OpenddsWrappers项目中,添加方法,处理opendds传输,主要有:

1、创建工厂

2、创建域

3、创建主题

4、创建发布者

5、创建订阅者

6、创建写入器

7.创建监听器

8、创建读取器

我这里就不一一贴代码了,有点多还是。这里主要一个分点是,一个域可以有多个发布者,一个发布者可以有多个写入器,每个写入器都有一个主题。这里开发时可以根据自己需要,我是每一个主题绑定一个写入器或则读取器,一个域中有唯一一个发布者或者订阅者。

理论上一个域可以有多个发布者或订阅者,这里有什么影响目前我还不知道,暂时就一个发布者和订阅者吧。

开发完以上代码,就是封装导出方法了,提供给c#使用。

#pragma once
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif#include"publisher.h"
#include"Subscriber.h"
#include"OpenddsWarp.h"
extern "C" {MYLIB_API int Addition(int a, int b);  MYLIB_API int Initopendds(int argc, char* argv[]);MYLIB_API int Createdomain(long id);MYLIB_API int PublishMsg(const  char* topicname,const unsigned  char* content,int lengh, int status, const char* from);MYLIB_API int PublishDomainMsg(long domainid, const  char* topicname, const unsigned  char* content, int lengh, int status, const char* from);MYLIB_API int SubscribeMsg(const  char* topicname, void (*func)(const char* , unsigned char*,long,long, const char* ));MYLIB_API int SubscribeDomainMsg(long domainid, const  char* topicname, void (*func)(const char*, unsigned char*,long ,long, const char*));
}

在项目上,加入预定义,然后编译。

2.添加c#项目DotNetForDDS,这是一个库,里面提供对c++导出的调用。

新建Wrappers类。

using System.Runtime.InteropServices;namespace DotNetForDDS
{public class Wrappers{/// <summary>/// 接收回调/// </summary>/// <param name="topic">主题</param>/// <param name="data">数据</param>/// <param name="datalen">数据长度</param>/// <param name="id">域ID</param>/// <param name="from">来源</param>[UnmanagedFunctionPointer(CallingConvention.Cdecl)]public delegate void FuncPtr(string topic, IntPtr data,long datalen,long id,string from);/// <summary>/// 测试函数/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>[DllImport("OpenddsWrappers.dll", CallingConvention = CallingConvention.Cdecl)]public static extern int Addition(int a, int b);/// <summary>/// 初始化,程序只调用一次/// </summary>/// <param name="argc"></param>/// <param name="agv"></param>/// <returns></returns>[DllImport("OpenddsWrappers.dll", CallingConvention = CallingConvention.Cdecl,CharSet =CharSet.Ansi)]public static extern int Initopendds(int argc, string[] agv);/// <summary>/// 创建域/// </summary>/// <param name="id">域ID</param>/// <returns></returns>[DllImport("OpenddsWrappers.dll", CallingConvention = CallingConvention.Cdecl)]public static extern int Createdomain(long id);/// <summary>/// 发布数据,在最新创建的域发布,一般程序中唯一域时/// </summary>/// <param name="topicname">主题</param>/// <param name="content">内容</param>/// <param name="len">内容长度</param>/// <param name="status">发布方式,0立即发布,1等待有订阅方初始化</param>/// <param name="from">标记发布源</param>/// <returns></returns>[DllImport("OpenddsWrappers.dll", CallingConvention = CallingConvention.Cdecl)]public static extern int PublishMsg(string topicname, byte[] content,int len, int status, string from);/// <summary>/// 指定域发布数据,没有域时会自动创建/// </summary>/// <param name="domainid">域ID</param>/// <param name="topicname">主题</param>/// <param name="content">内容</param>/// /// <param name="status">发布方式</param>/// <param name="from">标记源</param>/// <returns></returns>[DllImport("OpenddsWrappers.dll", CallingConvention = CallingConvention.Cdecl)]public static extern int PublishDomainMsg(long domainid, string topicname, byte[] content,int len, int status, string from);/// <summary>/// 订阅数据,最新创建域上订阅,一般一个域时/// </summary>/// <param name="topicname">主题</param>/// <param name="func">接收回调</param>[DllImport("OpenddsWrappers.dll", CallingConvention = CallingConvention.Cdecl)]public static extern void SubscribeMsg(string topicname, FuncPtr func);/// <summary>/// 指定域上订阅/// </summary>/// <param name="domainid">域ID</param>/// <param name="topicname">主题</param>/// <param name="func">接收回调</param>[DllImport("OpenddsWrappers.dll", CallingConvention = CallingConvention.Cdecl)]public static extern void SubscribeDomainMsg(long domainid, string topicname, FuncPtr func);}
}

这个调用库就完成了。

3.使用测试

添加c#控制台项目Test,引入DotNetForDDS性能,添加测试方法,验证订阅发布。

这里因为在同一个解决方案里面,可以通过c#直接调试到c++代码,具体可以网上搜索方法。

这里就不详细写了,有问题留言。测试效果:

当然这不完善,只是一个样例,目前是可以调用运行的,我还没有研究多线程的影响,内存释放这些,毕竟我对c++不熟悉。

http://www.xdnf.cn/news/2791.html

相关文章:

  • Android WebRTC回声消除
  • 具身智能:从理论突破到场景落地的全解析
  • 小目标检测的集成融合论文阅读
  • 项目实战-贪吃蛇大作战【补档】
  • 快速搭建对象存储服务 - Minio,并解决临时地址暴露ip、短链接请求改变浏览器地址等问题
  • 对比N+1查询和关联聚合查询
  • Spring Cloud Config 自定义配置源与动态刷新:从原理到企业级实践
  • Kafka 配置参数性能调优建议
  • 31、简要描述Promise.all的用途
  • 在 Ubuntu 22.04 x64 系统安装/卸载 1Panel 面板
  • 电子电器架构 ---电气/电子架构将在塑造未来出行方面发挥啥作用?
  • [Linux运维] [Ubuntu/Debian]在Lightsail Ubuntu服务器上安装Python环境的完整指南
  • 在线图书管理系统的结构化设计过程讲解
  • [密码学实战]SDF之设备管理类函数(一)
  • uniapp常用
  • case和字符串操作
  • 网络原理 - 10(HTTP/HTTPS - 1)
  • UniApp 实现分享功能
  • 深入探究C++ 中的stack、queue和deque
  • 图论---拓扑排序(DFS)
  • delphi使用sqlite3
  • 《AI大模型应知应会100篇》第39篇:多模态大模型应用:文本、图像和音频的协同处理
  • 基于 Python 的实现:居民用电量数据分析与可视化
  • C++入门(namespace/输入输出)
  • 2025A卷-正整数到Excel编号之间的转换
  • 对Electron打包的exe文件进行反解析
  • 在idea开发中遇到的20个bug
  • 晶振PCB设计核心要点与规范
  • 设备指纹护航电商和金融反欺诈体系建设
  • 飞凌嵌入式T527核心板获得【OpenHarmony生态产品兼容性证书】