google rpc(grpc)最新版本1.62.1以及使用vs2022的编译和运行(C++调用python端)

本文详细记录了作者在使用gRPC进行C++项目开发时,从克隆库、配置环境、解决编译错误(如`stdalign.h`缺失、SDK版本问题、不同C++标准等)到最后成功搭建Python客户端的全过程,分享了遇到的问题及解决方案,对初学者有参考价值。
摘要由CSDN通过智能技术生成

今日项目需要用到grpc,所以重拾了这个内容,也把这篇鸽了半年的csdn重新编写一下,相信这次可以写的更加全面

重要声明::此博客的部分技术和指导来源于b站的up主恋恋风辰zack,并且已经获得了转载许可

下面附上我参考的两篇文章的链接和简介,也欢迎各位去多多支持这位up,在一开始没有自主编译成功的时候我联系上了这位up,他给我提供了很多帮助,包括发送已经编译好的程序和借用百度网盘会员,希望大家能多多支持,下面是两个链接

【C++ 网络编程(24) windows环境下grpc配置和编译】 https://www.bilibili.com/video/BV1EP411e7p3/?share_source=copy_web&vd_source=1884bbfe3cf12a90e91b98a2694bd76e

【C++ 网络编程(25) 利用grpc通信】 https://www.bilibili.com/video/BV1gX4y1i7JL/?share_source=copy_web&vd_source=1884bbfe3cf12a90e91b98a2694bd76e

接下来我将结合大佬所给的文档以及我自己的一些自述,来重述我的整个过程

提示,由于本文章是一边攻克难题一边编写的,所以我把我遇到的所有问题都写在了里面,所以清各位务必先看一遍,然后选择其中正确的步骤进行操作,避免浪费时间,同时我也会把我遇到的过程和错误全部写进博客里面,为了防止大家误操作,或者按照直接配置的办法没办法运行,所以期间我会把我认为我做错了的操作重点标注,如果你看见我的路径从visual变成了newVisual请不要惊讶,这是我重新构建的

最终使用vs2022,vs2019会因为sdk版本不够高而报错

我是有加速器可以连接外网的,因此我在这里给大家展示的是不同于大佬的克隆过程

首先我们需要下载Git并且进行配置,这个过程大家可以自行进行搜索和配置,这部分是完全没有难度的

配置好git过后,我们新建一个文件夹叫grpc,打开加速器,然后输入这串代码

git clone https://github.com/grpc/grpc.git

克隆完成后是这个样子的

然后输入

git submodule update --init

这部分是根据这个目录下的.module中的追踪路径进行克隆

当然如果你有时间,也可以一点一点下载

如果出现了你输入命令后什么都没有发生,直接跳过,那么有可能是因为你的.git仓库不对,这种情况发生于你不是clone文件,而是直接下载了别人的release的压缩包造成的

更新后正常点入third_oparty,可以看到已经有了文件了

然后根据我发的视频中的文档,下载go,nasm和perl并且进行配置,并且下载Cmake,然后我们打开cmake,调整成如下,并且confugura,会发现报出一个警告

这段话的意思就是让我们打开一个选项,以确保可以成功构建,所以我们勾上,有的博客说不需要勾选,但我勾选过后是出问题的,我也说不清是不是这个选项的问题,但最终能运行的版本里面,是勾了这个选项的

然后generate

进入文件夹双击sln打开

找到ALL_BUILD点击重新生成,这里我其实一开始用的是默认,后来我改成了这个,把C++语言标准改成c++17,,这个后面再说

然后我就报错了。。这篇博客写到这里其实已经是一边编写博客一边操作了,我报错

C1083: 无法打开包括文件: “stdalign.h”: No such file or directory

直接把我CPU干烧了,我去查了一下然后找到了这篇博客

Windows GRPC源码编译C++库——详细步骤_a future abseil release will default absl_propagat-CSDN博客

然后我对里面的一句话感慨颇深

真的是痛苦面具,而且我用的是vs2019,即使我换成了最高的sdk还是会报错,所以。。不得不换成了vs2022,并且用cmake重新进行了编译,终于,这次不报错了,期间的warning直接不理会,只要不报错,那就是对的

编译完成过后,我们新建一个项目,并且根据大佬的博客我们写一个简单的协议,如下图所示

这里的两个HelloRequest和HelloReply其实相当于结构体,里面是你要传的数据,这个协议的写法也非常的深奥,我也不是很了解,就不献丑了

根据大佬的命令行代码我们进行编译生成

由于我的路径和大佬的不一样,所以这是我修改过后的路径,仅供大家参考,大家一定要多次检查这个路径,不然就会像我一样报错

编译过后就会生成这些文件了,并且添加进项目里面

然后是一个很痛苦的阶段,加入目录,这里推荐大家双击,用文件夹定位第一个目录以后,复制下来这个路径的共用部分,以节省时间,当然也可以一点一点配置,都没有关系(注:此处不要跟着操作!!!

下面是我加好过后的样子

继续配置库目录

最后我们要添加库的名字

注:以上不要跟着操作!!

最后按照大佬的方案写出来一个简易的客户端

注意,接下来的教程与大佬的就不同了,因为我的项目最终目标是C++调用python程序,所以这边我使用pycahrm来写接收端

首先我们要安装一下protobuf等必备组件,在下面了

grpc安装指令
pip install grpcio
pip install grpcio-tools  
pip install protobuf

然后编译的话用这个

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. 协议名字.proto

例如我这边是demo.proto,那就写成

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. demo.proto

然后就可以编写代码了(是不是很简单,但你说的对,这就是python。。。。。安装东西就install然后啊啊啊啊啊。。。。)

然后我们编写python作为服务端,我们一定不要起grpc这个名字,不然会出大问题,我已经出过问题并且改了

代码如下:这个代码是错误的,少了一部分东西,正确的代码在最下面!!

import time

import grpc
import demo_pb2 as pb2
import demo_pb2_grpc as pb2_grpc

from concurrent import futures

class Greeter(pb2_grpc.GreeterServicer):
    # def HelloReply(self, request, context):
    #     message = request.message
    def SayHello(self, request, context):
        message = request.message
        message = f'Service had received the request, the content is {message}!'
        return pb2.HelloReply(message=message)

def run():
    grpc_server = grpc.server(
        futures.ThreadPoolExecutor(max_workers=4)
    )#定义线程数量为4
    pb2_grpc.add_GreeterServicer_to_server(Greeter,grpc_server)#注册线程服务
    grpc_server.add_insecure_port('127.0.0.1:50051')#绑定端口号
    print("Starting server...")
    grpc_server.start()
    #使得python端grpc一直运行处理,不会运行一下就停止
    try:
        while True:
            time.sleep(3600)
    except KeyboardInterrupt as e:
        grpc_server.stop(0)


if __name__ == '__main__':
    run()

然后是可以正常挂起的,接着我们回到C++的项目,如果你已经尝试运行过就会知道,他会报错,当时也把我雷的不轻

然后我找了两篇别的博客看,他们都提到了需要构建INSTALL这个项目,那么我们来构建一下,首先退出vs,然后用管理员权限打开vs,这一步很重要,不然你会报错setlocal之类的,因为你权限不够

这个是我realease过后又debug了一下(写到这里又是几个小时过去了)

好的,现在经过了两天我已经能跑起来了,我来写一下最后的步骤,经过我和恋恋风辰azck大佬的沟通,在大佬的指点下,我启用了C++标准17,规避了这个报错,这在前文也有提到,这也是为什么我重新构建的原因,因为我害怕是构建allbuild的时候标准和现在不一致导致后面的报错

在之后运行的话,你会发现他会报错无法打开部分lib,这是因为新版本更新之后grpc的lib库新增和删除了很多,但无论你是用旧版本的还是删掉这些lib,都会报错无法解析的外部命令,是很多很多

这里我查过了,是没有答案的,所以以下步骤全是我自己用时间一点一点堆出来的,再次感谢恋恋风辰zack大佬对我的支持

我们修改库目录文件为如下

我这里的其实是这个路径

就是你intsall生成的grpc的目录下面,最后一个D盘的理论上可加可不加,我在后面会解释为什么我会加

连接器里面的常规改成如下图

然后链接库更新了很多,如下

这里我附上一段代码,是一个输出目录下全部文件的python运行程序,如果距离你看到这篇博客已经很久,或者静态库完全不一样,希望这一段代码可以帮到你

import os
filePath = 'path'#path为你要输出的文件路径
data = []
for i,j,k in os.walk(filePath):
    data.append(k)
    # print(i,j,k)
data = data[0]
count = 0
for i in range(0,len(data)):
    count+=1
    print(data[i])
print(count)

然后我加入这个之后,问题就来了,报错更多了

我当时就已经蒙了,问了大佬大佬跟我说你是不是链接库不对,或者debug用了release版本之类的,一开始我还没有在意,但是在面对这个问题进行尝试的时候,当我换了前两个目录,换回了大佬发的旧版本的目录,但是链接库没有换的时候,他开始报错说打不开一些.lib,我用everthing搜索了一下路径,发现有的lib是在debug里面的,而有的则是只在release里面,在那一瞬间我就意识到了这个问题,那就是我的c盘下生成的install里面既有release版本的,也有debug版本的,结合报错当中的release不匹配,我就开始一个一个删除掉release版本的库,在这里我给大家一个思路,如果你也混在了一起,你可以找到对应的release版本而不加入

最大的特征就是我的目录下有

而zlib.lib是release版本,zlibd.lib是debug版本,所以由此可见文件名高度相似的两个lib里面,带有d的是debug版本,这个仅供参考

下面是我的依赖库目录

absl_bad_any_cast_impl.lib
absl_bad_optional_access.lib
absl_bad_variant_access.lib
absl_base.lib
absl_city.lib
absl_civil_time.lib
absl_cord.lib
absl_cordz_functions.lib
absl_cordz_handle.lib
absl_cordz_info.lib
absl_cordz_sample_token.lib
absl_cord_internal.lib
absl_crc32c.lib
absl_crc_cord_state.lib
absl_crc_cpu_detect.lib
absl_crc_internal.lib
absl_debugging_internal.lib
absl_demangle_internal.lib
absl_die_if_null.lib
absl_examine_stack.lib
absl_exponential_biased.lib
absl_failure_signal_handler.lib
absl_flags_commandlineflag.lib
absl_flags_commandlineflag_internal.lib
absl_flags_config.lib
absl_flags_internal.lib
absl_flags_marshalling.lib
absl_flags_parse.lib
absl_flags_private_handle_accessor.lib
absl_flags_program_name.lib
absl_flags_reflection.lib
absl_flags_usage.lib
absl_flags_usage_internal.lib
absl_graphcycles_internal.lib
absl_hash.lib
absl_hashtablez_sampler.lib
absl_int128.lib
absl_kernel_timeout_internal.lib
absl_leak_check.lib
absl_log_entry.lib
absl_log_flags.lib
absl_log_globals.lib
absl_log_initialize.lib
absl_log_internal_check_op.lib
absl_log_internal_conditions.lib
absl_log_internal_fnmatch.lib
absl_log_internal_format.lib
absl_log_internal_globals.lib
absl_log_internal_log_sink_set.lib
absl_log_internal_message.lib
absl_log_internal_nullguard.lib
absl_log_internal_proto.lib
absl_log_severity.lib
absl_log_sink.lib
absl_low_level_hash.lib
absl_malloc_internal.lib
absl_periodic_sampler.lib
absl_random_distributions.lib
absl_random_internal_distribution_test_util.lib
absl_random_internal_platform.lib
absl_random_internal_pool_urbg.lib
absl_random_internal_randen.lib
absl_random_internal_randen_hwaes.lib
absl_random_internal_randen_hwaes_impl.lib
absl_random_internal_randen_slow.lib
absl_random_internal_seed_material.lib
absl_random_seed_gen_exception.lib
absl_random_seed_sequences.lib
absl_raw_hash_set.lib
absl_raw_logging_internal.lib
absl_scoped_set_env.lib
absl_spinlock_wait.lib
absl_stacktrace.lib
absl_status.lib
absl_statusor.lib
absl_strerror.lib
absl_strings.lib
absl_strings_internal.lib
absl_string_view.lib
absl_str_format_internal.lib
absl_symbolize.lib
absl_synchronization.lib
absl_throw_delegate.lib
absl_time.lib
absl_time_zone.lib
absl_vlog_config_internal.lib
address_sorting.lib
cares.lib
crypto.lib
gpr.lib
grpc++.lib
grpc++_alts.lib
grpc++_error_details.lib
grpc++_reflection.lib
grpc++_unsecure.lib
grpc.lib
grpcpp_channelz.lib
grpc_authorization_provider.lib
grpc_plugin_support.lib
grpc_unsecure.lib
libprotobuf-lited.lib
libprotobufd.lib
libprotocd.lib
re2.lib
ssl.lib
upb_base_lib.lib
upb_json_lib.lib
upb_mem_lib.lib
upb_message_lib.lib
upb_textformat_lib.lib
utf8_range.lib
utf8_range_lib.lib
utf8_validity.lib
zlibd.lib
zlibstaticd.lib

到这里就基本差不多了,最后,他会报一个错误,是xxx.exe找不到依赖库zlib.dll,然后我就加了上面图片的第一个D盘路径,就是那么来的,。。他还报错。。,所以我直接把dll移动到了生成的exe下面,然后不报错了,就。。挺莫名其妙的

然后你正常情况下开起来pycahrm服务端和C++客户端,然后正常情况下你就又可以报错了,报错什么什么missing 1 required positional argument 'context'

然后这个错误是最恶心的,为什么这么说呢,你以为这是C++的错误?错!,这其实是python端的错误,没想到吧,当我折腾了两个小时C++然后才意识到这个问题的时候我只想一拳干碎电脑

原因就在于,你少了一个括号

就是这,看到没?Greeter要加括号

这是修改后的正确代码

import time

import grpc
import demo_pb2 as pb2
import demo_pb2_grpc as pb2_grpc

from concurrent import futures

class Greeter(pb2_grpc.GreeterServicer):
    # def HelloReply(self, request, context):
    #     message = request.message
    def SayHello(self, request, context):
        message = request.message
        message = f'Service had received the request, the content is {message}!'
        return pb2.HelloReply(message=message)

def run():
    grpc_server = grpc.server(
        futures.ThreadPoolExecutor(max_workers=4)
    )#定义线程数量为4
    pb2_grpc.add_GreeterServicer_to_server(Greeter(),grpc_server)#注册线程服务
    grpc_server.add_insecure_port('127.0.0.1:50051')#绑定端口号
    print("Starting server...")
    grpc_server.start()
    #使得python端grpc一直运行处理,不会运行一下就停止
    try:
        while True:
            time.sleep(3600)
    except KeyboardInterrupt as e:
        grpc_server.stop(0)


if __name__ == '__main__':
    run()

然后运行起来就可以了,附上截图

到这里,这篇历时三天的博客就结束了,最后依旧感谢一下恋恋风辰zack大佬的帮助,顺便再求一个赞,这几天一直都是搞到夜里10点,除了睡觉都在尝试,包括晚饭都是拿两个包子就回宿舍继续搞,孩子真是本科生啊

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值