1

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.

sama
  • 333
  • 2
  • 11
  • I know the name of symbol the problem is that this the way that we create shared librarry from a cpp file when it contains classes differs from when cpp file only contains FUNCTIONS I am looking for the way that I have implement client.cc – sama Nov 10 '22 at 14:07
  • I added minimal example. – sama Nov 10 '22 at 15:09
  • Did you use the same code and called RunCLient method? because for me I get error Segmentation fault (core dumped). How did you build the .so file and how did you run UDF? which command? – sama Nov 10 '22 at 16:26
  • But still problem with the main program exists. do you have any idea? – sama Nov 11 '22 at 09:47
  • I cannot test your program as it has multiple dependencies. Please create a [mcve]. – Lorinczy Zsigmond Nov 11 '22 at 10:06
  • As It is related to gRPC I can this is the minimal program that I can create, I can Add server.cc and then you have to install gRPC to test it. Do you mind to help me with it? Thanks so much. – sama Nov 11 '22 at 10:08
  • Try to add this to the compiler-options of `libclient_lib.so`: `-Wl,--no-undefined` It might help to find the missing dependency when building libclient_lib.so – Lorinczy Zsigmond Nov 11 '22 at 15:16

1 Answers1

1

client_lib looks like a shared-object which should have complete symbols. You can try to add ${hw_proto_srcs} to client_lib.

Esun Kim
  • 189
  • 1