1 思考历程
最近有些加我微信的知友私信我说,如何通过Qt调用python,如何通过java调用C++动态库等一系列的不同语言相互调用的问题。
关于这个问题,你只需要在百度搜索框中搜索,就会出来很多相关的帖子,但真正应用到自己系统中时,往往会遇到很多问题,比如环境、系统、兼容、版本问题等。这经常会耗费好几天的时间才能真正解决。
那对于这些问题,有没有一个通用的解决方案呢,我也思考了良久,现在也想通了一些,故分享给大家,也是对我自己做一次总结。
在开始之前,我想先总结下不同语言相互调用的方法
1)Qt调用Python:需要加载python库,及包含python的头文件
2)Python调用动态库:需导入ctypes模块,需要将python的数据类型转化为C或C++中的数据类型
3)Java调用动态库:需使用jni进行调用,也会涉及到数据类型相互转换
...
面对如此多的复杂方式,我们应该怎样才能提出一个通用的解决方案呢。
现在我们试想如果把两种编程语言设想成是两个应用程序,那么应用程序之间的交互应该如何处理,即进程之间应如何处理,这使我想到了IPC(进程间通信)
好,既然是IPC,那么IPC总共包含以下几种方式
除去socket外,其它ipc方式,都会频繁的涉及到资源同步问题,而使用socket我们可以有效避免这类问题,且不需要处理复杂的数据类型转换。
为此,我们再进一步推演,既然是socket,那么有没有现成的框架或设计方式可以供我们参考,答案肯定是有的,那就是现在非常流行的C/S架构(不明白的可百度自行搜索)
2 为什么如此做
参考上图:
我们将传统的语言相互调用的模式,转化成了C/S架构,总结起来可以有如下优点
1)屏蔽环境问题:不同语言相互调用的复杂环境问题,只需部署好各自的运行环境。例如:
a. 语言版本不兼容
b. 操作系统32位或64位兼容性问题
c. 调用的第三方库对环境有依赖
2)屏蔽语言数据类型差异:不需要对不同语言所支持的数据类型做转化,使用通用Json语言进行序列化或反序列化即可。例如:
a. 有符号和无符号之间的转换
b. 字符串宽窄字符转换
c. 不同编码类型的转换
3)应用隔离:两种语言是相互隔离的,在架构设计时,隔离性是必须要考虑到的。例如:
a. 当被调用的C++程序需要调用一个较新的功能或引用一个新的动态库,而使用此功能必须需要升级C++版本
b. 被调用方如果崩溃,会引起调用方崩溃
c. 可单独进行监控、自动化mock测试、代码优化
4)不必部署在同台机器上:socket连接可使两个应用单独部署,如果后期需要,可以不改变代码的情况下灵活切换。例如:
a. 调用其它语言一般是要进行复杂运算,为提高运算速度和稳定性,可将此部分灵活的切换到服务器上
b. 有些应用要求的磁盘或内存空间有限,需要将某些功能移动到服务器上,这样可有效减少体积
c. 某些应用并不想暴露过多的细节给客户,为安全考虑,可将这部分移动到服务器上单独部署
对于此种方式,有些同学可能会担心性能上的问题,一般情况下此种结构是部署在同机上的,对于现代硬件速度,这种差异几乎是可以忽略不计的。
3 如何做
既然好处这么多,那如何做呢
3.1 选择通信协议
既然是socket,那首先要考虑用什么协议,直接使用原生的socket,小豆君还是不太建议,这里你得处理很多跟应用无关的东西。鉴于是同机应用相互调用,使用websocket还是比较好的选择。
在不同的语言环境中,大家可以直接在百度搜索就可以看到很多关于websocket的调用方法,这里就不介绍了。
3.2 路由表
既然是服务端,就要对外提供接口,起初我们会这样定义:
{ "interface": "getUserName", "params": {"userName": "wang"} } { "interface": "setSystemInfo", "params": {"sysName": "win"} }
但是当你的接口增多时,这样的方式就会很混乱,所以你要将众多的接口进行分类整理,这时候就可以使用路由表,路由表可以使用“/”进行分隔,如
{ "interface": "users/get/by/name", "params": {"userName": "wang"} } { "interface": "sys/set/all", "params": {"sysName": "win"} }
注意此路由表不必与实际目录真实对应,此处仅表示逻辑对应
3.3 版本号
为了进行兼容,你应该在你的接口中增加版本号等兼容性信息,如果不填,则可以使用默认设置
3.4 为你的接口增加mock
增加mock单元测试,可以使你很容易的构造测试用例,并且保证代码有足够的稳定性
最后,每当我们工作中遇到问题时,百度出来的解决方案往往不适用当前环境,为此我们可能会花掉好几天的时间来解决问题,这是一个非常烦心的事情
为解决这种困境,小豆君会针对每个主题问题汇总到一篇文章中,当大家遇到问题时,只需要在我的这篇文章中查找即可解决,省时省力,同时也可以快速获取知识,提高工作效率,升职加薪(*^▽^*)
好了,关于今天的分享就到这里了,socket通信并不是万能的,还需根据实际情况进行综合考量。
互联网是开放开源的世界,每个有志有识之人都乐于分享,喜欢本文的你就支持一下吧
微信号:小豆君编程分享 (关注后,可加入小豆君交流群进行学习交流,也可第一时间看到最新文章)
头条号:小豆君编程分享