I am writing a gRPC code which is going to converted to .so file and using that shared library I am going to call the service from a mySQl UDF. This is my client.cc:
#include <grpcpp/grpcpp.h>
#include <string>
#include "stringreverse.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using stringreverse::StringReply;
using stringreverse::StringRequest;
using stringreverse::StringReverse;
class StringReverseClient {
public:
StringReverseClient(std::shared_ptr<Channel> channel)
: stub_(StringReverse::NewStub(channel)) {}
// Assembles client payload, sends it to the server, and returns its response
std::string sendRequest(std::string a) {
// Data to be sent to server
StringRequest request;
request.set_original(a);
// Container for server response
StringReply reply;
// Context can be used to send meta data to server or modify RPC behaviour
ClientContext context;
// Actual Remote Procedure Call
Status status = stub_->sendRequest(&context, request, &reply);
// Returns results based on RPC status
if (status.ok()) {
return reply.reversed();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC Failed";
}
}
private:
std::unique_ptr<StringReverse::Stub> stub_;
};
extern "C" std::string RunClient() {
std::string target_address("0.0.0.0:50051");
// Instantiates the client
StringReverseClient client(
// Channel from which RPCs are made - endpoint is the target_address
grpc::CreateChannel(target_address,
// Indicate when channel is not authenticated
grpc::InsecureChannelCredentials()));
std::string response;
std::string a = "grpc is cool!";
// RPC is created and response is stored
response = client.sendRequest(a);
// Prints results
std::cout << "Original string: " << a << std::endl;
std::cout << "Reversed string: " << response << std::endl;
return response;
}
extern "C" int main(int argc, char* argv[]) {
RunClient();
return 0;
}
this is my stringreverse.proto
syntax = "proto3";
package stringreverse;
// The string reversal service definition.
service StringReverse {
// Function invoked to send the request
rpc sendRequest (StringRequest) returns (StringReply) {}
}
// The request message containing the original string
message StringRequest {
string original = 1;
}
// The response message containing the reversed string
message StringReply {
string reversed = 1;
}
and this is my UDF.cc
extern "C" std::string stringreverse(UDF_INIT *initid, UDF_ARGS *args,
std::string result, unsigned long *length,
char *is_null, char *error)
{
void* handle = dlopen("./libclient_lib.so", RTLD_LAZY);
if (handle == NULL)
{
fprintf(stderr, " %s\n", dlerror());
}
// load the symbol
typedef std::string (*RunClient_t)();
RunClient_t RunClient = (RunClient_t) dlsym(handle, "RunClient");
result=RunClient();
dlclose(handle);
return result;
}
extern "C" bool stringreverse_init (UDF_INIT *initid, UDF_ARGS *args, char *message)
{
return 0;
}
extern "C" void stringreverse_init_deinit (UDF_INIT *initid)
{
return;
}
This is server.cc:
#include <grpcpp/grpcpp.h>
#include <string>
#include "stringreverse.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using stringreverse::StringReply;
using stringreverse::StringRequest;
using stringreverse::StringReverse;
// Server Implementation
class ReverseServiceImplementation final : public
StringReverse::Service {
Status sendRequest(ServerContext* context, const StringRequest*
request,
StringReply* reply) override {
// Obtains the original string from the request
std::string a = request->original();
// String reversal
int n = a.length();
for (int i = 0; i < n / 2; i++) std::swap(a[i], a[n - i - 1]);
reply->set_reversed(a);
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
ReverseServiceImplementation service;
ServerBuilder builder;
// Listen on the given address without any authentication mechanism
builder.AddListeningPort(server_address,
grpc::InsecureServerCredentials());
// Register "service" as the instance through which
// communication with client takes place
builder.RegisterService(&service);
// Assembling the server
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on port: " << server_address <<
std::endl;
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}
and this is CMAkelists.txt:
# Minimum CMake required
cmake_minimum_required(VERSION 3.15)
# Project
project(stringreverse)
# Protobuf
set(protobuf_MODULE_COMPATIBLE TRUE)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${protobuf_VERSION}")
# Protobuf-compiler
set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
# gRPC
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
set(_GRPC_GRPCPP gRPC::grpc++)
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
# Proto file
get_filename_component(hw_proto "stringreverse.proto" ABSOLUTE)
get_filename_component(hw_proto_path "${hw_proto}" PATH)
# Generated sources
set(hw_proto_srcs
"${CMAKE_CURRENT_BINARY_DIR}/stringreverse.pb.cc")
set(hw_proto_hdrs
"${CMAKE_CURRENT_BINARY_DIR}/stringreverse.pb.h")
set(hw_grpc_srcs
"${CMAKE_CURRENT_BINARY_DIR}/stringreverse.grpc.pb.cc")
set(hw_grpc_hdrs
"${CMAKE_CURRENT_BINARY_DIR}/stringreverse.grpc.pb.h")
add_custom_command(
OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}"
"${hw_grpc_srcs}" "${hw_grpc_hdrs}"
COMMAND ${_PROTOBUF_PROTOC}
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
-I "${hw_proto_path}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
"${hw_proto}"
DEPENDS "${hw_proto}")
# Include generated *.pb.h files
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
include_directories("/home/sama/grpc/include")
# Targets (client|server)
foreach(_target
client server)
add_executable(${_target} "${_target}.cc"
${hw_proto_srcs}
${hw_grpc_srcs})
target_link_libraries(${_target}
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})
endforeach()
add_library(client_lib SHARED client.cc)
target_link_libraries(client_lib
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF}})
First I create libclient_lib.so from my client.cc then use it in my UDF, but I get error ./libclient_lib.so: undefined symbol: _ZTVN13stringreverse13StringReverse4Stub5asyncE Segmentation fault (core dumped)
Could you please tell me how can I sole the problem with stringreverse.grpc.pb.h.