一、OpenDDS编译及安装
参考文章:
(26条消息) OpenDDS搭建教程(Windows10)_lcynone的博客-优快云博客_opendds
(27条消息) VS2015编译OpenDDS_csdn菜逼的博客-优快云博客
(27条消息) OpenDDS环境搭建-Windows 10_PP.Lee的博客-优快云博客_opendds环境配置
出现的问题有:
1.OpenDDS编译不通过,且由于版本不匹配,没能在configure找到413行编辑插入。
解决方案:编译时要启动VS开发人员命令行!!!非命令提示符!!!注意版本问题,不同版本之间不一定兼容。我用高版本的ACE+TAO编译低版本的OpenDDS,同样不成功。我主要是按照第一篇文章进行环境搭建,选择了如下版本:
OpenDDS-3.14
ACE+TAO-6.5.12
编译采用的是VS2019,编译过程中未出现修改configure文件的情况。
2.使用过程中出现缺失静态库的情况。
解决方案:编译过程中Win32/x64的选择要与配置OpenDDS环境时编译的选择保持一致,不然会提示报错"无法解析的外部符号"。配置时就要选好是32位还是64位。
二、OpenDDS基础架构学习
2022年9月25日:
参考文章:
(27条消息) opendds简单入门(二)_飞鸟真人的博客-优快云博客
DDS开发_lyingbo_新浪博客 (sina.com.cn)
(27条消息) OPenDDS程序 的 实现+运行_PP.Lee的博客-优快云博客_opendds使用
主要参考第三篇文章。
过程中会用到的cmd:
cd D:\opendds\TEST-DDS-220926
perl %ACE_ROOT%\MPC\mwc.pl -type vs2019 -include %DDS_ROOT%\MPC\config
注意:编译过程中Win32/x64的选择要与配置OpenDDS环境时编译的选择保持一致,不然会提示报错"无法解析的外部符号"。
贴一个关闭防火墙的方法:
Win10如何关闭防火墙?Win10关闭防火墙的方法 - 知乎 (zhihu.com)
在一台电脑上的实现结果:
三、编写项目中出现的问题
2022/10/04
1.编译的项目总是不通过,显示如下:
解决方法:还是按照二中第三篇文章的方法生成三个项目,然后将这三个项目合并,改掉主函数名,并且将配置属性->常规->配置类型->改为动态库(.dll)
根本解决方式:改掉两个.idl文件的属性,与原本项目中idl文件的属性一致即可。
2.一个解决方案下好几个项目间互用需要注意的问题:
1、在解决方案中更改项目依赖项。
2、依赖项目的配置类型改成动态库(.dll),且配置属性->高级->字符集修改成与主项目相同的配置。
3、主项目中附加包含目录、附加库目录、附加依赖项等都需加入依赖项目的内容。
4、依赖项目编译成功,但主项目编译不通过,且提示缺文件/函数,有时是因为头文件的顺序问题,将依赖项目的头文件在主项目中提前,有时会解决这些奇怪的报错。
上图所示即为将依赖项目的头文件“DDSData.h”提前。
3.编译通过,但启动控制台调试器时提示缺少dll库
visual studio 运行找不到dll库 - 半夜打老虎 - 博客园 (cnblogs.com)
采用上述文章中的方法4,如下:
在 项目-属性- 配置属性 -调试-环境中添加:
PATH=${YourDllDirectory}\build\bin\Debug
其中
${YourDllDirectory}
是你自己定义的环境变量,在这里就可以使用这个宏,当然也可以直接使用绝对路径。
如果有多个路径的话可以用%3b(即分号)隔开。最后,要注意Debug和Release的dll库是不同的,根据配置环境选择不同的dll库。例如:PATH=D:\build1\bin\Debug%3bD:\build2\bin\Debug
4.无法解析的外部符号
(22条消息) 无法解析的外部符号解决方法汇总_吴一奇的博客-优快云博客_无法解析的外部符号
今天出现的问题就是二、高级玩家看中列出的问题。
<pre name="code" class="cpp">//TestB.h
#ifdefine PROJECT_B
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif
class DLL TestB{
//....
};
项目B中在"属性->C++->预处理器->预处理器定义"中定义PROJECT_B,这样,项目B就申明类TestB为__declspec(dllexprot);而项目A包含了头文件TestB.h,但是没有定义预处理器宏PROJECT_B,则申明TestB为__declspec(dllimport)。
5.如何将opendds与QT相结合
通过二中的参考文章三,我们已经掌握了生成exe文件调用opendds的方法,但是将其如何写成一个动态库的函数,然后在项目中直接调用函数,达到使用opendds的目的呢?相当于我们要改写main函数,但main函数中有两个输入参数,非常困扰。
//以XDataSubscriber.cpp中的main函数举例
int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) {
try
{
// 初始化参与者
argv[1] = "-DCPSConfigFile";
argv[2] = "config_Sub.ini";
argc = 3;
// 1. 初始化参与者
DDS::DomainParticipantFactory_var dpf =
TheParticipantFactoryWithArgs(argc, argv);
DDS::DomainParticipant_var participant =
dpf->create_participant(111,
PARTICIPANT_QOS_DEFAULT,
DDS::DomainParticipantListener::_nil(),
::OpenDDS::DCPS::DEFAULT_STATUS_MASK);
if (CORBA::is_nil(participant.in())) {
cerr << "create_participant failed." << endl;
return 1;
}
//以下省略
//...
}
}
argc的输入好解决,argv[1]与argv[2]的输入也可以解决。但是argv[0]始终不知道如何输入,最终在GitHub上找到了相同的问题。
OpenDDS in MFC Application · Issue #3058 · objectcomputing/OpenDDS · GitHub
解答:
Please open a pull request with changes needed to support MFC.
When we have seen this kind of issue before it's been because ACE::init()
needs to be called. See the file ACE/ace/Init_ACE.h
in GitHub - DOCGroup/ACE_TAO: ACE and TAO
解决步骤:
1.初始化前,添加头文件#include <ace/Init_ACE.h>
2.初始化前,调用ACE::init();实体清理后,调用ACE::fini()
3.argc和argv如下写:
//初始化生成XData的收发数据成员
int GenXDataMembers() {
//初始化ACE
ACE::init();
const int nNUMBER_OF_ARGUEMENTS = 2;
int argc = nNUMBER_OF_ARGUEMENTS;
ACE_TCHAR* argv[nNUMBER_OF_ARGUEMENTS] = { ACE_TEXT("-DCPSConfigFile"), ACE_TEXT("config_Pub.ini") };
//1. 初始化参与者
DDS::DomainParticipantFactory_var dpf =
TheParticipantFactoryWithArgs(argc, argv);
//以下省略
//...
}