项目需啊将网站上传的图片传入c++推理引擎,网站使用flask架构,python编写,图片推理引擎是一个单独的server,c++编写,因此用grpc来传输比较合适。理论上来说只要规定好proto文件,即使语言不通也是可以实现客户端和服务端的交互的。下面是一个简单的demo,结构如下。

grpc demo python客户端 c++服务端_#include

 

 客户端和服务端的proto文件是一致的,其实最好就用一个文件,把它放在上级目录中,这里图方便就复制了一份,下面是test.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.example.test";
option java_outer_classname = "TestProto";
option objc_class_prefix = "HLW";

package test;

message Data { int32 data = 1; }

message ReplyMsg { string message = 1; }

service CommunicationTest {
rpc getData(Data) returns (ReplyMsg) {}
}

c++ server生成grpc代码的脚本

# mkdir gen_code
/usr/local/bin/protoc --version
/usr/local/bin/protoc -I ./ --grpc_out=./gen_code --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./test.proto
/usr/local/bin/protoc -I ./ --cpp_out=./gen_code ./test.proto

python client生成grpc代码的脚本

python -m grpc_tools.protoc -I ./ --python_out=./gen_code --grpc_python_out=./gen_code ./test.proto

c++ server端代码

#include <grpc/grpc.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server.h>
#include <grpcpp/server_builder.h>
#include <grpcpp/server_context.h>

#include <iostream>
#include <string>
#include <memory>

#include "./gen_code/test.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::ServerReader;
using grpc::ServerReaderWriter;
using grpc::ServerWriter;
using grpc::Status;

class TestImpl final : public test::CommunicationTest::Service
{
public:
grpc::Status getData(grpc::ServerContext *context, const test::Data *data, test::ReplyMsg *msg) override
{
std::cout << "grpc get data: " << data->data() << std::endl;
std::string tmp("data received successful, this is reply message");
msg->set_message(tmp);
return grpc::Status::OK;
}
};

void RunServer()
{
TestImpl service;
grpc::ServerBuilder builder;
builder.AddListeningPort("0.0.0.0:50051", grpc::InsecureServerCredentials());
builder.RegisterService(&service);

std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
std::cout << "Server listening on 0.0.0.0:50051" << std::endl;
server->Wait();
}

int main(int argc, char **argv)
{
RunServer();
return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(test)

find_package(Threads REQUIRED)
find_package(Protobuf CONFIG REQUIRED)

set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
set(_REFLECTION gRPC::grpc++_reflection)

find_package(gRPC REQUIRED)
set(_GRPC_GRPCPP gRPC::grpc++)

# proto file
get_filename_component(test_proto "../test.proto" ABSOLUTE)
get_filename_component(test_proto_path "${test_proto}" PATH)

# generated sources
include_directories("${CMAKE_CURRENT_BINARY_DIR}/../gen_code")
set(test_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/../gen_code/test.pb.cc")
set(test_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../gen_code/test.pb.h")
set(test_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/../gen_code/test.grpc.pb.cc")
set(test_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/../gen_code/test.grpc.pb.h")

# hw_grpc_proto
add_library(hw_grpc_proto
${test_grpc_srcs}
${test_grpc_hdrs}
${test_proto_srcs}
${test_proto_hdrs})
target_link_libraries(hw_grpc_proto
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})

foreach(_target
test_server test_client
)
add_executable(${_target} "${_target}.cc")
target_link_libraries(${_target}
hw_grpc_proto
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})
endforeach()

python client代码

from __future__ import print_function

import logging
import grpc
from gen_code import test_pb2, test_pb2_grpc

def run():
print("Will try python grpc test")
input_data = input("input message: ")
with grpc.insecure_channel('localhost:50051') as channel:
stub = test_pb2_grpc.CommunicationTestStub(channel)
response = stub.getData(test_pb2.Data(data=int(input_data)))
print("test client received: "+ response.message)

if __name__ == '__main__':
logging.basicConfig()
run()

grpc demo python客户端 c++服务端_python_02

 

 

grpc demo python客户端 c++服务端_#include_03

 

 结果如图

无情的摸鱼机器