`

ICE之Application 和 slice到C++映射

阅读更多

ICE是ZeroC公司开发的一款高效的开源中间件平台,全称是Internet Communications Engine。

它的主要设计目标是:
1 提供适用于异种环境的面向对象中间件平台。
2 提供一组完整的特性,支持广泛的领域中的实际的分布式应用的开发。
3避免不必要的复杂性,使平台更易于学习和使用。
4 提供一种在网络带宽、内存使用和 CPU 开销方面都很高效的实现。
5提供一种具有内建安全性的实现,使它适用于不安全的公共网络。

ICE支持多种编程语言:C++、Java、C#、VB、Python、Ruby,也就是说使用ICE时我们可以让这些语言无缝沟通,不过由于ICE是用C++编写的,不管用什么语言,你都需要先用C++编译出一个ICE才行(或者下载已编译的版本)。

本篇文章以C++语言作为演示语言,其它语言除语法不同外,使用方法非常类似。

配置ICE开发环境

首先,从http://www.zeroc.com/download.html 下载ICE,目前最新版本是Ice-3.3.1。下载页面里除了ICE的源码之外,也提供了VC或C++Builder的已编译安装包以及各Linux版本的RPM下载。

如果下载的是源码版本,编译方法是(以VC2005 Express为例):

1. ICE需要一些第三方库,在编译ICE之前要先编译第三方库,清单如下(它们也能在ICE官网上下载):

Berkeley DB  expat  OpenSSL  bzip2  mcpp

2. 编译完上面这些库以后,把它们放到同一个目录中,然后设置环境变量THIRDPARTY_HOME:

set THIRDPARTY_HOME = d:\ice3party

3. 打开$ICE/cpp/Make.rules.mak,找到CPP_COMPILER变量,改成CPP_COMPILER = VC80_EXPRESS
    这个依据你的编译器决定,可以是VC60, VC80, VC80_EXPRESS, VC90, VC90_EXPRESS, BCC2007, BCC2009

4. 如果想让编译的库能脱离VC运行时库,打开$ICE/cpp/Make.rules.msvc,把CPPFLAGS    = $(CPPFLAGS) -MD改成CPPFLAGS    = $(CPPFLAGS) -MT。

5. 在命令行下进入$ICE/cpp目录,输入nmake -f Makefile.mak开始编译。默认是编译成Debug模式的DLL库。如果想编译成静态库,可以设置变量STATICLIBS=yes;想编译成Release模式,设置OPTIMIZE=yes。如

nmake -f Makefile.mak STATICLIBS=yes OPTIMIZE=yes

如果按上面方法设置,应该不会有问题。

6. 最最后,把bin目录加入path变量,以便让系统能找到ICE的dll文件(其实主要是三个dll文件,ice33.dll、iceutil33.dll和bzip2.dll)

以后编译ICE的程序时,把上面编译好或直接下载的已编译版本的ice.lib和iceutil.lib(或Debug版本的iced.lib和iceutild.lib)链接入项目即可。

 

 

ICE的HelloWorld

跨语言的分布式系统首先要定义一个与编程语言无关的接口描述语法,用于分布于各处的服务器与客户端之间对话。比如DCOM和CORBA使用IDL语法,SOAP使用WSDL语法,当然还有时下流行的JSON。

ICE使用的是称为Slice(Specificatoin Language for Ice)的语法,Slice语法和C++(或Java,C#)比较相近,只要会C++(或Java,C#)很容易就能写Slice定义了

下面是一个简单的接口的Slice定义:

  1. module Demo {
  2.     interface Printer {
  3.         void printString(string s);
  4.     };
  5. };

它定义一个Printer接口(interface),这个接口只有一个printString方法,输入参数是一个字符串(string)。最后,这个接口位于Demo模块(module)之下。

把它保存为Printer.ice后接着我们使用slice2cpp程序依据这个Slice定义生成C++使用的头文件和对应的代理代码:

slice2cpp Printer.ice

如果没提示错误,就会生成Printer.h和Printer.cpp,把这两个文件加入到服务器端项目和客户端项目后就可以互相对话了。

下表是Slice与C++的映射关系

Slice C++
#include #include
#ifndef #ifndef
#define #define
#endif #endif
module namespace
bool bool
byte Ice::Byte
short Ice::Short
int Ice::Int
long Ice::Long
float Ice::Float
double Ice::Double
string Ice::string
enum enum(不支持指定数字)
struct struct
class class(所有方法都是纯虚函数)
interface struct(所有方法都是纯虚函数,没有成员变量)
sequence<T> std::vector<T>
dictionary<Key,Value> std::map<Key,Value>
exception Err class Err:public Ice:UserException
nonmutating方法限定符 const方法
idempotent方法限定符 -
out 参数限定符 引用类型
* 对应类型的代理类

参考这个表,可以知道上面的Slice定义对应的C++映射如下:

  1. namespace Demo {
  2.     struct Printer {
  3.         virtual void printString(string s) = 0;
  4.     };
  5. };

严格地说,C++中对应的Printer类还继承自IceProxy::Ice::Object,目前我们可以不理这个问题

我们只要在服务器端实现这个printString方法,就可以在客户端简单地调用它了。

编写服务器端代码:

  1. 新建一个控制台项目
  2. 将$ICE\include添加到头文件目录列表中
  3. 将$ICE\lib\ice.lib和iceutil.lib(对应的Debug版本是iced.lib和iceutild.lib)链接入项目
  4. 把生成Printer.cpp加入项目
  1. #include <ice/ice.h>
  2. #include "printer.h"  //slice2cpp生成的文件
  3. using namespace std;
  4. using namespace Demo;
  5. //实现printString方法
  6. struct PrinterImp : Printer{
  7.     virtual void printString(const ::std::string& s,
  8.         const ::Ice::Current& = ::Ice::Current())
  9.     {
  10.         cout << s << endl;  
  11.     }
  12. };
  13. int main(int argc, char* argv[])
  14. {
  15.     Ice::CommunicatorPtr ic;
  16.     try{
  17.         // 初始化Ice运行库
  18.         ic = Ice::initialize(argc, argv);
  19.         // 建立ObjectAdapter,命名为SimplePrinterAdapter
  20.         // 使用默认协议(一般是tcp)并在10000端口监听。
  21.         Ice::ObjectAdapterPtr adapter
  22.             = ic->createObjectAdapterWithEndpoints(
  23.                 "SimplePrinterAdapter""default -p 10000");
  24.         // 把我们实现的Printer加入ObjectAdapter,并命名为SimplePrinter
  25.         Ice::ObjectPtr object = new PrinterImp;
  26.         adapter->add(object, ic->stringToIdentity("SimplePrinter"));
  27.         adapter->activate();
  28.         // 等待直到Communicator关闭
  29.         ic->waitForShutdown();
  30.     }
  31.     catch(const Ice::Exception &e){
  32.         cerr << e << endl;
  33.     }
  34.     catch(const char* msg){
  35.         cerr << msg << endl;
  36.     }
  37.     // 回收Ice运行库所用的资源
  38.     if(ic) ic->destroy();
  39.   
  40.     return 0;
  41. }

客户端代码:

  1. #include <ice/ice.h>
  2. #include <printer.h>
  3. using namespace std;
  4. using namespace Demo;
  5. int main(int argc, char* argv[])
  6. {
  7.     Ice::CommunicatorPtr ic;
  8.     try{
  9.         // 初始化Ice运行库
  10.         ic = Ice::initialize(argc, argv);
  11.         // 在10000端口取得SimplePrinter代理对象
  12.         Ice::ObjectPrx base = ic->stringToProxy("SimplePrinter:default -p 10000");
  13.         // 把对象转换成Printer代理
  14.         PrinterPrx printer =  PrinterPrx::checkedCast(base);
  15.         if(!printer) throw "Invalid Proxy!";
  16.         // 能过这个代码调用printString方法
  17.         printer->printString("Hello World!");
  18.     }
  19.     catch(const Ice::Exception &e){
  20.         cerr << e << endl;
  21.     }
  22.     catch(const char* msg){
  23.         cerr << msg << endl;
  24.     }
  25.     // 回收Ice运行库所用的资源
  26.     if(ic) ic->destroy();
  27.   
  28.     return 0;
  29. }

编译服务器端和客户端,然后启动一个服务器端,每次调用客户端后服务器端会显示一行Hello world!

你也可以把服务器端放到别的电脑上,客户端代码改成:Ice::ObjectPrx base = ic->stringToProxy("SimplePrinter:default -h 服务端IP -p 10000");即可实现远程调用。

看上去我们写一个Helloworld的程序要弄这么一大堆的东西,不过实际上只要我们修改Slice定义,我们就可实现更强大的功能,而代码并不需要多大变化。

 

使用Ice::Application简化代码的编写

对比上例中的服务端和客户端代码,可以发现占很大比例的代码都是初始化、异常捕捉、回收资源这样的“样板”代码。ICE针对这些“样板”代码提供了Ice::Application类来封装它们(而且它做得更多),通过它我们就可以简化上例中了代码了。

Ice::Application中有一个纯虚函数

virtual int run(int, char*[]) = 0;


我们只要实现这个run方法,其它的一切都由Application完成:

服务器端:

  1. #include <ice/ice.h>
  2. #include "printer.h"
  3. using namespace std;
  4. using namespace Demo;
  5. struct PrinterImp : Printer{
  6.     virtual void printString(const ::std::string& s, const ::Ice::Current& = ::Ice::Current())
  7.     {
  8.         cout << s << endl;  
  9.     }
  10. };
  11. class MyApp : public Ice::Application{
  12. public:
  13.     virtual int run(intchar*[]){
  14.         Ice::CommunicatorPtr& ic = communicator();
  15.         Ice::ObjectAdapterPtr adapter
  16.             = ic->createObjectAdapterWithEndpoints(
  17.                 "SimplePrinterAdapter""default -p 10000");
  18.         Ice::ObjectPtr object = new PrinterImp;
  19.         adapter->add(object, ic->stringToIdentity("SimplePrinter"));
  20.         adapter->activate();
  21.         ic->waitForShutdown();
  22.         return 0;
  23.     }
  24. };
  25. int main(int argc, char* argv[])
  26. {
  27.     MyApp app;
  28.     return app.main(argc, argv);
  29. }

原来的版本我们的退出方法只能使用很野蛮的强行退出,现在,服务端可以检测到Ctrl+C这样的退出信号了。

客户端:

  1. #include <ice/ice.h>
  2. #include <printer.h>
  3. using namespace std;
  4. using namespace Demo;
  5. class MyApp: public Ice::Application{
  6. public:
  7.     virtual int run(intchar*[])
  8.     {
  9.         Ice::CommunicatorPtr ic = communicator();
  10.         Ice::ObjectPrx base = ic->stringToProxy("SimplePrinter:default -p 10000");
  11.         PrinterPrx printer =  PrinterPrx::checkedCast(base);
  12.         if(!printer) throw "Invalid Proxy!";
  13.         printer->printString("Hello World!");
  14.     }
  15. };
  16. int main(int argc, char* argv[])
  17. {
  18.     MyApp app;
  19.     return app.main(argc,argv);
  20. }
分享到:
评论

相关推荐

    ICE框架 C++示例程序

    4. **自动类型映射**:ICE支持基本数据类型和自定义类型的自动序列化和反序列化,简化了数据交换的过程。 5. **透明的负载均衡和故障恢复**:ICE内置了负载均衡和故障恢复机制,可以动态调整服务实例,确保系统的高...

    ICE中间件教程

    - **1.3.2 Slice映射机制**:定义了如何将Slice中的定义映射到具体的编程语言中,如C++或Java。 **1.4 Ice协议** - **1.4.1 Ice协议的组成**:包括消息格式、序列化规则等,确保客户端和服务器之间的通信能够高效...

    新化县建材家居协会电子商务频道共建专项方案.doc

    新化县建材家居协会电子商务频道共建专项方案.doc

    电动车控制器79HF9211:三相无刷电机矢量控制与智能驱动程序详解

    内容概要:本文详细介绍了79HF9211电动车控制器的程序架构及其关键实现细节。首先探讨了三相无刷电机的矢量控制,包括PWM频率设置、死区时间配置以及相电流采样的自校准。接着讨论了电机启动时采用的缓升策略,特别是线性斜坡函数的应用、初始力矩限制和霍尔传感器消抖处理。然后阐述了过流保护机制,强调了q轴电流监测和故障处理方法。最后提到了通信层的一些特殊功能,如CAN协议中的调试指令和安全冗余设计的重要性。 适合人群:从事电动车控制系统开发的技术人员,尤其是对三相无刷电机矢量控制感兴趣的工程师。 使用场景及目标:帮助开发者深入了解79HF9211控制器的工作原理和技术细节,掌握其编程技巧并应用于实际项目中,确保系统的高效性和稳定性。 其他说明:文中提供了多个代码片段作为实例,便于读者理解和实践。同时提醒使用者注意某些高级功能(如解除温度保护)可能带来的风险。

    PMSM FOC+SVPWM仿真模型与DSP28335代码实现及10kw永磁电机实验验证 · SVPWM 宝典

    内容概要:本文介绍了针对10千瓦永磁同步电机(PMSM)的FOC(磁场定向控制)+SVPWM(空间矢量脉宽调制)仿真模型及其在DSP28335芯片上的代码实现。首先阐述了实验背景与目的,旨在通过仿真模型深入了解PMSM的动态特性和有效控制策略。接着详细描述了基于MATLAB/Simulink平台构建的仿真模型,涵盖电机数学模型、控制算法及信号处理流程,重点在于矢量控制策略如电流环、速度环和磁场控制。随后展示了仿真的验证结果,表明模型能精确模拟电机运行状态并提升功率因数和效率。最后,文中详述了DSP28335代码实现部分,确保了电机控制算法的核心逻辑得以正确执行。实验验证显示,所提出的控制策略使电机运行稳定,响应迅速,满足预期性能指标。 适合人群:从事电机控制系统研究的技术人员、高校相关专业师生、对电机控制感兴趣的工程技术人员。 使用场景及目标:适用于需要理解和掌握PMSM FOC+SVPWM控制方法的研究人员和技术开发者,帮助他们更好地设计和优化电机控制系统,提高电机运行效率和控制精度。 其他说明:文章还提到未来将在此基础上进一步探索更多应用场景,优化现有模型与代码,以适应更广泛的实际需求。

    西门子PLC动态密码程序解析:适用于1200与1500PLC的SCL编写催款程序及动态密保

    内容概要:本文详细介绍了西门子PLC动态密码程序的设计与实现,特别针对1200PLC和1500PLC型号。该程序主要用于催款业务场景,采用了SCL(结构化控制语言)进行编写,提供了动态密保功能,增强了系统安全性和用户账户的保密性。文章从程序的编写思路、操作步骤到实际应用场景进行了全面解析,强调了其在提升工作效率、减少人为错误以及保障企业信息安全方面的优势。文中还提到,该程序具有高度的通用性和灵活性,适用于不同的业务需求,并配有详细的视频讲解,帮助用户更好地理解和操作。 适合人群:从事工业自动化控制领域的工程师和技术人员,尤其是熟悉或希望深入了解西门子PLC编程的人士。 使用场景及目标:①需要在工业控制系统中实施催款程序的企业;②希望通过增强动态密保功能提升系统安全性的企业;③希望掌握SCL编程技巧并应用于实际项目中的技术人员。 其他说明:该程序不仅提升了系统的安全性和可靠性,还在效率和准确性方面表现出色,为企业带来了更多商业机会和发展空间。

    数据库仓库管理系统课程设计.doc

    数据库仓库管理系统课程设计.doc

    数据库实验3.doc

    数据库实验3.doc

    基于映射关系的领域词典抽取算法.zip

    基于映射关系的领域词典抽取算法.zip

    工业自动化领域中基于西门子PLC与ABB机器人的立库码垛系统实现及应用

    内容概要:本文介绍了一个典型的工业自动化应用场景——立库码垛机,重点讲述了如何利用西门子PLC、ABB机器人、视觉系统(基恩士相机)、伺服轴和西门子变频器G120 Profinet等设备进行高效协同作业。文中详细描述了系统架构、设备选型、通信协议(MODBUS TCP)及其编程方法(SCL和梯形图混编),并展示了具体的程序实现与调试步骤。此外,还探讨了系统测试与优化过程,确保立库码垛机在不同工况下的稳定性和高性能表现。 适合人群:从事工业自动化领域的工程师和技术人员,特别是对PLC编程、机器人控制和视觉系统感兴趣的读者。 使用场景及目标:适用于需要提升物流与仓储中心自动化水平的企业和个人。目标是通过引入先进的自动化技术和设备,提高生产效率和精度,降低人工成本。 其他说明:本文不仅提供了详细的理论讲解,还包括丰富的实际操作经验分享,有助于读者更好地理解和掌握相关技术。

    基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)

    基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目),个人经导师指导并认可通过的高分设计项目,评审分98分,项目中的源码都是经过本地编译过可运行的,都经过严格调试,确保可以运行!主要针对计算机相关专业的正在做大作业、毕业设计的学生和需要项目实战练习的学习者,资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基于JavaWeb的学生信息管理系统课程设计源码+数据库+文档报告(99分项目)基

    同一套代码适配多种数据库最终方案代码示例

    同一套代码适配多种数据库最终方案代码示例

    新能源光伏综合自动化设备技术规范书.doc

    新能源光伏综合自动化设备技术规范书.doc

    文泰雕刻软件使用说明书上半部分.doc

    文泰雕刻软件使用说明书上半部分.doc

    三菱FX-5U PLC轴定位与Modbus RTU RS-485通信案例解析及应用

    内容概要:本文介绍了三菱FX-5U PLC在自动化生产线中的轴定位控制及其与测微计通过Modbus RTU RS-485通信的具体实现方法。文中详细描述了编程软件、PLC与触摸屏程序、地址规划表以及相关手册和视频教程的应用。通过实例展示了如何解决编程实践中遇到的各种挑战,如硬件接线和软件逻辑错误等问题。最终,成功实现了高精度的轴定位和稳定的数据通信。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对三菱FX系列PLC和Modbus RTU通信感兴趣的读者。 使用场景及目标:适用于希望深入了解三菱FX-5U PLC轴定位技术和Modbus RTU RS-485通信机制的专业人士。目标是掌握这两种关键技术的实际应用技巧,提高自动化系统的性能和可靠性。 其他说明:附带的编程示例有助于读者理解和实践文中提到的技术细节。同时提供的视频教程可以作为辅助学习材料,帮助初学者更快上手。

    电动两轮车领域的高性能FOC电机控制方案:基于国产芯片的成熟解决方案

    内容概要:本文介绍了应用于电动两轮车(如电动自行车、滑板车)的大厂成熟FOC电机控制方案。该方案基于国产Gd32F150芯片,提供了多种功能,包括转把三速切换、刹车功能、助力功能、电子刹车、欠压检测、巡航功能、铁塔王通讯、一键通、隐形限速、防盗功能、霍尔修复、自学习和故障显示等。此外,该方案配备上位机进行直观调试和波形显示,确保电机控制的稳定性和准确性。代码和PCB文件已更新并优化,适用于量产。 适合人群:电动两轮车制造商、硬件工程师、嵌入式系统开发者以及对电动出行设备感兴趣的爱好者。 使用场景及目标:① 提供稳定的电机控制方案,确保电动两轮车的安全性和可靠性;② 利用上位机进行高效调试,优化电机性能;③ 实现多种智能化功能,提升用户体验。 其他说明:该方案不仅适用于电动自行车和滑板车,还可以扩展到其他电动出行设备。其强大的功能和良好的兼容性使其成为电动出行设备开发的理想选择。

    基于COMSOL的原油脱水电-磁场耦合模型:双液滴聚结行为与影响因素分析 文档

    内容概要:本文介绍了利用COMSOL Multiphysics建立的原油脱水模型,重点探讨了在外加交流电场条件下,原油乳化液中双液滴的聚结行为及其影响因素。模型通过耦合静电场、层流场和电流守恒场,精确模拟了电场强度、界面张力和液滴直径等因素对聚结速率的影响。研究表明,适当的电场强度(如3 MV/m)可以显著提高聚结效率,而过高或过低的电场强度则可能导致相反效果。此外,界面张力和液滴直径也在聚结过程中起到关键作用,特别是当界面张力低于0.01 N/m时,液滴会迅速合并。仿真结果显示,最佳聚结速度并不出现在最高电场强度处,而是存在一个最优值。 适用人群:从事石油工程、化学工程及相关领域的研究人员和技术人员。 使用场景及目标:适用于需要解决原油脱水问题的炼油厂和其他相关企业。目标是通过优化电场条件和物理参数,提升原油脱水效率,降低生产成本。 其他说明:文中提供了具体的MATLAB代码片段用于创建和调整模型,以及详细的参数设置方法,为实际应用提供了指导。同时,强调了电场和流场耦合的重要性,提出了传统方法之外的新思路。

    教育类网站建设方案介绍.doc

    教育类网站建设方案介绍.doc

    西门子1200 PLC程序管理汽车零部件压装工艺:12位置压力位移采集与工艺流程简化

    内容概要:本文详细介绍了基于西门子1200系列PLC的汽车零部件压装工艺管理系统。该系统针对12个压装位置的压力和位移数据采集进行了优化,采用模块化编程方式,实现了复杂工艺流程的简化。文中具体描述了数据采集功能块的设计,包括双缓冲采集机制、压力和位移传感器的数据处理方法以及状态机架构的应用。此外,还讨论了工位协同控制、交流电机调速、版本兼容性等问题,并展示了系统的实际应用效果,如压装不良率显著降低。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程和汽车制造工艺感兴趣的读者。 使用场景及目标:适用于需要提高生产效率和质量控制的汽车零部件制造企业。主要目标是通过先进的PLC编程技术和数据采集手段,优化生产工艺流程,减少不良品率。 其他说明:文中提供了具体的编程实例和解决方案,有助于读者理解和应用相关技术。

    数据库语言SQL专题培训.pptx

    数据库语言SQL专题培训.pptx

Global site tag (gtag.js) - Google Analytics