RCFProto及编译

    公司在规划一款产品,涉及到异构语言的client-server通信。但xml-rpc的方案相对臃肿缓慢,最终的消息编码协议选择了Google的ProtoBuffer。接着选择一款RPC实现,重点考虑以下问题:

  • 产品开发语言支持:比如C++、Java、C#,甚至python
  • 跨平台支持:支持Window、Linux,最好也支持移动系统
  • 稳定:不考虑技术新奇的新生框架,要求有稳定的版本
  • 应用广泛:有广泛应用的框架不会缺乏维护
  • 文档全面:应用人员易于接手

    RCFProto是基于RCF网络库的GoogleProtocol Buffers的RPC实现。RCFProto在多种平台下(Windows、Linux和OS X)支持4种语言(C++、C#、Java、Python)。它结合了RCF的快速、可扩展,以及Protocol Buffers的高效、可移植和自动版本消息。在2014-04-25发布了1.0.0.1版本,在2015-06-01发布了1.1.0.0版本。而RCF从2008年发布的第一个正式版本1.0,到现在的2.01,经历了7个比较重大的版本变化,发展的用户包括”爱立信、惠普“等这样的大公司,在网络上查找RCF相关的介绍,负面反馈几乎没有,是功能比较强大的分布式通信框架,比较稳定,比较成熟。支持TCP、UDP、HTTP、HTTPS、命名管道等多种通信协议。官方文档号称使用了零拷贝、零堆内存分配、Server端缓存等技术,用于提高性能。(我说了这么多,并不是认为它有多好,使用ASIO或者libuv之类的网络框架直接使用google protocol buffers更简洁,但你不用给人解释protobuf的编解码过程了,也不用解释libuv是什么了,直接使用client对象连接server对象就好了)

    由于编译环境复杂,在过程中还是遇到了一些问题。(本文所取RCFProto的版本为2.6.1)

Windows下编译

visual studio 2015:

会出现找不到外部符号的编译错误。

src\google\protobuf\generated_message_util.cc:50

const ::std::string * empty_string_ = 0; //加上 LIBPROTOBUF_EXPORT 

要是还有问题,就把头文件中的inline函数定义移到.cc文件中吧。

Mingw:

共发现两处错误

1、seed_rng.hpp:242:20: error: 'winapi' in namespace  'boost::detail' does not name a type
     boost::detail::winapi::HCRYPTPROV_ random_;

解决方法:
boost_1_59_0\boost\uuid\seed_rng.hpp:41
#if defined(_MSC_VER) 修改为 #if defined(BOOST_WINDOWS)

2、 ..\cpp\src\RCFProto.cpp: In member function 'void RCF::RcfProtoServer::ProtoRpcBeginCpp(RCF::RcfProtoSession&, const string&, int)':
..\cpp\src\RCFProto.cpp:780:5: error: reference to 'Service' is ambiguous   Service * pService = NULL;
原因是 ntsecapi.h有如下定义,导致跟google::protobuf::Service冲突:
#ifndef _NTLSA_IFS_
  typedef enum _SECURITY_LOGON_TYPE {
    Interactive = 2,Network,Batch,Service,Proxy,Unlock,NetworkCleartext,NewCredentials,RemoteInteractive,CachedInteractive,
    CachedRemoteInteractive,CachedUnlock
  } SECURITY_LOGON_TYPE,*PSECURITY_LOGON_TYPE;
#endif
指定命名空间,使用google::protobuf::Service 替换 Service

Linux下编译:

1、需要动态库(libRCFProto.so)而不是静态链接库(libRCF.a、libRCFProto.a)
查看cpp/demo/make/Makefile,会发现如下的东西
RCF.o:
g++ -fPIC -c ../../src/RCF/src/RCF/RCF.cpp -DRCF_BUILD_DLL -DRCF_USE_ZLIB -DRCF_USE_OPENSSL -I/home/user/Development/boost_1_49_0 -I../../src -I../../src/RCF/include

RCFProto.o:
g++ -fPIC -c ../../src/RCFProto.cpp -DRCF_BUILD_DLL -DRCF_USE_ZLIB -DRCF_USE_OPENSSL -I/home/user/Development/boost_1_49_0 -I../../src -I../../src/RCF/include

libRCFProto.so: RCFProto.o RCF.o
g++ -shared -o libRCFProto.so RCFProto.o RCF.o -lpthread -lprotobuf -ldl
将Boost的include路径修改为系统中Boost的路径
RCF.o: 
g++ -fPIC -c ../../src/RCF/src/RCF/RCF.cpp -DRCF_BUILD_DLL -DRCF_USE_ZLIB -DRCF_USE_OPENSSL -I$(BOOST_DIR) -I../../src -I../../src/RCF/include

RCFProto.o: 
g++ -fPIC -c ../../src/RCFProto.cpp -DRCF_BUILD_DLL -DRCF_USE_ZLIB -DRCF_USE_OPENSSL -I$(BOOST_DIR)  -I../../src -I../../src/RCF/include
然后make,就能得到.so文件了

2、运行Java Demo错误:

运行Java Demo时的加载.so连接库错误:按照原工程编译demo,运行时会产生错误:
DemoServer exception:
Unable to load RCFProto native bindings for Java. Make sure libRCFProto_Java_impl.so can be loaded from java.library.path.
System.loadLibrary() error: java.lang.UnsatisfiedLinkError: /home/zf/work/opensource/RCFProto-src-1.1.0.0/java/bin/x64/libRCFProto_Java_impl.so: /home/zf/work/opensource/RCFProto-src-1.1.0.0/java/bin/x64/libRCFProto_Java_impl.so: undefined symbol: _ZTIN3RCF18UdpServerTransportE
java.library.path: /usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib:/home/zf/work/opensource/RCFProto-src-1.1.0.0/java/bin/x64

解决方法:
CMakeFiles/RCFProto_Java_impl.dir/build.make:88: recipe for target 'libRCFProto_Java_impl.so' failed

打开这个文件,定位到88行:
87     libRCFProto_Java_impl.so: CMakeFiles/RCFProto_Java_impl.dir/link.txt
   88     @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --red --bold "Linking CXX shared library libRCFProto_Java_impl.so"

查看87行提到的link.txt文件:
/usr/bin/c++ -fPIC  -g -shared -Wl,-soname,libRCFProto_Java_impl.so -o libRCFProto_Java_impl.so CMakeFiles/RCFProto_Java_impl.dir/cpp/src/swig/RCFProto_Java_impl.cpp.o  libRCFProto.a libRCF.a -lprotobuf -lpthread -ldl
修改为:
 /usr/bin/c++  -fPIC  -g   -shared -Wl,-soname,libRCFProto_Java_impl.so -o libRCFProto_Java_impl.so CMakeFiles/RCFProto_Java_impl.dir/cpp/src/swig/RCFProto_Java_impl.cpp.o  -lRCFProto -lprotobuf -lpthread -ldl -L./

Android NDK:

找不到Java(xubuntu 15.04):
安装了oracle的JDK,也设置了环境变量,还是不行,只能一个一个手动修改了
提示boost库找不到:
设置Boost_INCLUDE_DIR,而不是提示的“BOOST_INCLUDEDIR"(很难想象配置脚本的制作人员犯这种错误)

编译错误:
/RCFProto-src-1.1.0.0-Android/cpp/src/RCF/include/RCF/external/asio/asio/impl/error_code.ipp:103:45: error: invalid conversion from 'int' to 'const char*' [-fpermissive]

return strerror_r(value_, buf, sizeof(buf)); 
查找strerror_r函数手册后发现,此函数在不同的系统下声明竟然是不同的(这里选择的NDK的版本是最新的r10e),修改方法如下:
strerror_r(value_, buf, sizeof(buf));
return buf;




你可能感兴趣的:(RCFProto及编译)