RCF的简单使用教程以及什么是回调函数

RCF的使用教程

RCF(Remote Call Framework)是一个使用C++编写的RPC框架,在底层RCF支持多种传输实现方式(transport implementations). 包括TCP,UDP,多播,组播,win32命名管道和unix domain socket。下面我以一个例子讲述如何使用TCP完成一次RPC操作。

需要注意的是,RCF官网上提供的是源码包,所以在使用时我们要么自己将其编译为动态库,要么将整个源码加入我们的项目中。

1. 定义接口

使用RCF框架,我们不必像CORBA那样,需要使用IDL去定义接口。直接使用RCF提供的宏就可以定义。

以下代码定义了一个名为I_PrintService的接口,该接口包含了名为Print的函数,函数返回值为void,参数是const string &类型。

值得注意的是RCF_METHOD_V1表示函数返回值为空且只有一个形参,类似的,RCF_METHOD_V2表示函数返回值为空且有两个参数,最多支持15个参数。那么如果我们想要函数有返回值呢?比如一个返回值为int,有一个参数的函数。这时可以使用RCF_METHOD_R1宏来声明该函数。严谨一点的表达如下所示,

RCF_METHOD_{V|R}{

// Define the I_PrintService RCF interface.
RCF_BEGIN(I_PrintService, "I_PrintService")
    RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)

2. 服务端的编写

该代码的目的是在服务端实现一个Print函数,然后客户端使用自己的参数调用服务端的Print函数。

  1. 创建一个初始化对象RcfInit init. RcfInit的默认构造函数会调用init(RcfConfigT *=nullptr)初始化RCF库的引用计数值。
  2. 实例化一个RCF server,参数是具体的传输方式,TCP,UDP,命名管道等等。
  3. 将服务器绑定到声明的接口
  4. 启动服务器
#include <iostream>
#include <RCF/RCF.hpp>
// Define the I_PrintService RCF interface.
RCF_BEGIN(I_PrintService, "I_PrintService")
    RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)
// Server implementation of the I_PrintService RCF interface.
class PrintService
{
public:
    void Print(const std::string & s)
    {
        std::cout << "I_PrintService service: " << s << std::endl;
    }
};

int main()
{
    try
    {
        // Initialize RCF.
        1. RCF::RcfInit rcfInit;
        // Instantiate a RCF server.
        2. RCF::RcfServer server(RCF::TcpEndpoint("127.0.0.1", 50001));
        // Bind the I_PrintService interface.
        3. PrintService printService;
        server.bind<I_PrintService>(printService);
        // Start the server.
        4. server.start();
        std::cout << "Press Enter to exit..." << std::endl;
        std::cin.get();
    }
    catch ( const RCF::Exception & e )
    {
        std::cout << "Error: " << e.getErrorMessage() << std::endl;
    }
    return 0;
}

3. 客户端的编写

  1. 声明接口
  2. 创建一个初始化对象RcfInit init.
  3. 实例化一个RCF客户端
  4. 调用服务器的函数
RCF_BEGIN(I_PrintService, "I_PrintService")
    RCF_METHOD_V1(void, Print, const std::string &)
RCF_END(I_PrintService)
int main()
{
    try
    {
        // Initialize RCF.
        RCF::RcfInit rcfInit;
        std::cout << "Calling the I_PrintService Print() method." << std::endl;

        // Instantiate a RCF client.
        RcfClient<I_PrintService> client(RCF::TcpEndpoint("127.0.0.1", 50001));
        // Connect to the server and call the Print() method.
        client.Print("message from dennis");
    }
    catch ( const RCF::Exception & e )
    {
        std::cout << "Error: " << e.getErrorMessage() << std::endl;
    }
    return 0;
}

4. 编译运行

编译时注意添加头文件的目录和-luuid

g++ server.cpp ../src/RCF/RCF.cpp -lpthread -ldl -std=c++1y -luuid -I ../include/ -o server

参考

http://www.deltavsoft.com/doc/_init_deinit_8hpp.html#a450dd848bd45776c9a277ded406522c1

回调函数(callback)

1. 什么是回调函数

回调函数就是由调用方实现,但是由被调用函数(库函数)调用的函数。常见于c标准库和java,c++中的事件处理机制。回调函数可分为两种同步回调和异步回调。


2. 同步回调

同步回调函数在调用方(caller)调用后立即执行

下面我们以一个c实例讲解什么是同步回调,以及使用回调函数的好处。

可以看到在server.c中,我们定义的库函数为callbk,该函数接受三个参数,前两个参数是函数指针fp的参数。

在头文件server.h中我们声明了一个接口funcp,该接口是一个接受两个int参数,返回值为int的函数指针。

---

库函数的实现

//   server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "server.h"

int callbk(int a, int b, funcp fp)
{
    return fp(a, b);
}

//   server.h
#ifndef _SERVER_H
#define _SERVER_H
typedef int (*funcp)(int, int);
int callbk(int, int, funcp);
#endif

我们可以将server.c制作成动态库并将其放置到/usr/lib目录中

> gcc -shared -fPIC server.c -o libserver.so

调用方的实现

调用方调用库函数,并将自己实现的函数作为参数传递给库函数callbk。

#include "server.h"

int add_int(int a, int b)
{
    return (a+b);
}

int main()
{
    int sum = callbk(1, 2, add_int);
    printf("sum=%d\n", sum);
    return 0;
}

以上就是同步回调的实现。


3. 异步回调

异步回调在unix编程,窗口程序,以及需要事件处理机制的程序中被广泛使用。举几个例子,

1 pthread创建线程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                  void *(*start_routine) (void *), void *arg);

2 unix注册信号处理函数

以下代码为信号SIGUSR1注册了一个用户自定义的sig_usr函数

if ( signal(SIGUISR1, sig_usr)  == SIG_ERR)
    perrror("sig err");

3 java swing

以下代码用户自定义了回调类MyListener

class MyListener implements ActionListener
{
    ...
    public void actionPerformed(ActionEvent event)
    {
            //some operation
    }
}

JButton yButton = new JButton();
yButton.addActionListener(new MyListener);

4. reference

https://www.ibm.com/developerworks/cn/linux/l-callback/

https://blog.csdn.net/morixinguan/article/details/65494239

http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26000296&id=5782305

https://en.wikipedia.org/wiki/Callback_(computer_programming)

https://stackoverflow.com/questions/9596276/how-to-explain-callbacks-in-plain-english-how-are-they-different-from-calling-o/9652434#9652434

原文地址:https://www.cnblogs.com/dennis-wong/p/9149636.html

时间: 2024-10-18 07:46:27

RCF的简单使用教程以及什么是回调函数的相关文章

使用回调函数,简单模拟dbutils中Queryrunner的工作原理,并重写Queryrunner,使其使用起来更加简单方便

所谓回调,就是在执行某个程序时,具体的封装处理由第三方类来实现,简单一点说就是记录内部,再出来(由第三方类可以对数据进行处理),再返回去继续执行,这个过程就是回调.想要程序具有记录内部的功能就必须定义一个规范,也就是接口,即你的程序出来被其他类处理了,但你规定了还要返回原程序. 下面看一个简单的例子: /** * @描述:回调函数--记录内部,再出来返回去的过程就叫回调 * @author cxie */ public class CopyOfCallBackDemo { public stat

程序员,一起玩转GitHub版本控制,超简单入门教程 干货2

本GitHub教程旨在能够帮助大家快速入门学习使用GitHub,进行版本控制.帮助大家摆脱命令行工具,简单快速的使用GitHub. 做全栈攻城狮-写代码也要读书,爱全栈,更爱生活. 更多原创教程请关注头条号.每日更新.也可以添加小编微信:fullstackCourse.一起交流,获取最新全栈教程信息.因为FQ原因,不能下载客户端的同仁,可以关注后回复“GitHub客户端”获取安装软件. 上篇教程:GitHub这么火,程序员你不学学吗? 超简单入门教程 干货 GitHub概念部分出现了一丝纰漏.为

spring4.0.6最新稳定版新特性学习,简单学习教程(一)

Spring Framework 4.0 学习整理. Spring框架的核心部分就是Ioc容器,而Ioc控制的就是各种Bean,一个Spring项目的水平往往从其XML配置文件内容就能略知一二,很多项目,往往是外包公司的项目,配置文件往往是乱七八糟,抱着能跑就行,不报错就行的态度去写,然后在项目中后期发现各种缺失又去一通乱补,其结果就是,整个文档可读性极差,毫无章法.这也不能怪写这个XML的人,拿着苦逼程序员的工资干着架构师的工作必然是这个结果.为了程序员的幸福,我认为有必要来一套简单快速的官方

iBatis简单入门教程

iBatis 简介: iBatis 是apache 的一个开源项目,一个O/R Mapping 解决方案,iBatis 最大的特点就是小巧,上手很快.如果不需要太多复杂的功能,iBatis 是能够满足你的要求又足够灵活的最简单的解决方案,现在的iBatis 已经改名为Mybatis 了. 官网为:http://www.mybatis.org/ 搭建iBatis 开发环境: 1 .导入相关的jar 包,ibatis-2.3.0.677.jar .mysql-connector-java-5.1.6

Swift简单入门教程:30分钟玩转Swift

通常来说,编程语言教程中的第一个程序应该在屏幕上打印“Hello, world”.在 Swift 中,可以用一行代码实现:    println("hello, world") 如果你写过 C 或者 Objective-C 代码,那你应该很熟悉这种形式——在 Swift 中,这行代码就是一个完整的程序.你不需要为了输入输出或者字符串处理导入一个单独的库.全局作用域中的代码会被自动当做程序的入口点,所以你也不需要main函数.你同样不需要在每个语句结尾写上分号. 这个教程会通过一系列编程

github简单使用教程

github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开.对于一般人来说公共仓库就已经足够了,而且我们也没多少代码来管理,O(∩_∩)O~.下面是我总结的一些简单使用方法,供初学者参考. ~~廖雪峰老师关于git的教程写得很好,可以百度来看看 1.注册账户以及创建仓库 要想使用github第一步当然是注册github账号了.之后就可以创建仓库了(免费用户只能建公共仓库),Create a New Repository,填好名称后Cr

OpenMP的简单使用教程

转自:http://binglispace.com/2015/01/09/openmp-intro/ OpenMP的简单使用教程 今天有幸参加了一个XSEDE OpenMP的workshop讲座,真是受益匪浅啊.简单来说OpenMP就是一个多线程程序的框架.和MPI相比,MPI每一个Node都有独立的内存空间,但是OpenMP所有的线程共享一个内存空间.显而易见,OpenMP的硬件制约要比MPI大,但是只要硬件跟得上就会比MPI要快.OpenMP一般都会部署再超级计算机中心,但是几年之前它就成为

knockout简单实用教程3

在之前的文章里面介绍了一些KO的基本用法.包括基本的绑定方式,基本的ko的绑定语法包括text绑定,html绑定等等(如有不明请参照上两篇文章),下面呢介绍一下关于ko的其他方面的知识.包括比较特殊绑定方式和语法还有KO官方mapping插件的使用等等.对了在前面的文章中好像漏掉了属性绑定的的介绍.那就先简单介绍下.属性绑定吧.直接上代码. <a data-bind="attr: { href: url, title: details }"> Report </a&g

IOS游戏源码下载之简易版雷电(2.2.3版本)源码完整下载和简单开发教程

 头回写教程这玩意,真不知道要写些什么,所以主要就是共享下我的代码,和一些重要功能的讲解吧,各位如果有啥不懂的可以回帖提问哟. 其实这个demo(为何叫demo呢,因为我真不敢称这个为游戏呀)是我初学cocos2d-x两周的时候写的,所以可能写的不是很好(好吧,其实现在写的东西也不好),当初主要还是靠着度娘和TestCpp学的,所以在此还是要强调一下TestCpp的重要性,要好好把它看一遍哟,以后你想实现什么功能就可以去翻看了. 好了,言归正传,还是介绍下我写的这个demo了,在此先华丽丽的