0

I have project structure like this,

a.pb.h          --- includes -->    protobuf.h
b.grpc.pb.h     --- includes -->    a.pb.h & grpcpp.h

Also there are a.pb.cc and b.grpc.cc files.

A C++ wrapper with extern C which is wrapper.cc and wrapper.h which includes b.grpc.pb.h and grpcpp.h. The function inside extern C is char* helloWorld(const char*, const char*, const char*);

Creating .o of a.pb.h and b.grpc.pb.h:

g++ -fpic -std=c++11 `pkg-config --cflags protobuf grpc`  -c -o a.pb.o a.pb.cc
g++ -fpic -std=c++11 `pkg-config --cflags protobuf grpc`  -c -o b.grpc.pb.o b.grpc.pb.cc

Steps to create libcombined.so:

The grpc and protobuf so are already provided under /usr/local/lib. First created .so of a.pb.o and b.grpc.pb.o to compile wrapper file as:

g++ -shared -o libcombined.so *.o

Compiled wrapper as:

g++ -fpic wrapper.cc -l:./libcombined.so -c -o wrapper.o -std=c++11

.so of a.pb.o, b.grpc.pb.o and wrapper.o as libcombined.so:

g++ -shared -o libcombinedwrapper.so *.o

Compiled main.c as:

gcc main.c -l:./libcombinedwrapper.so -o main -ldl

I am calling helloWorld from my main.c file which is:

#include <stdio.h>
#include <dlfcn.h>

int main(){
    char* (*fn)(const char*,const char*,const char*);
    void *handle  = dlopen("path_to/libcombined.so",RTLD_NOW);
    if(handle==NULL){
        fprintf(stderr, "Error: %s\n", dlerror());
    }
    fn = (char* (*)(const char*,const char*,const char*))dlsym(handle, "helloWorld");
    if (!fn) {
        /* no such symbol */
        fprintf(stderr, "Error: %s\n", dlerror());
        dlclose(handle);
        return 0;
    }
    char* msg = fn("asd","asdas","asdasd");
    printf("%s",msg);
    return 0;
}

Error after executing: ./main

Error: path_to/libcombinedwrapper.so: undefined symbol: _ZN6google8protobuf2io20ZeroCopyOutputStream15WriteAliasedRawEPKvi
Error: ./main: undefined symbol: helloWorld
Segmentation fault (core dumped)

The first above error is from symbol from protobuf.h file.

Can someone please suggest what I am doing wrong while linking or is there something I am doing wrong in main.c file?

Prasha
  • 371
  • 1
  • 3
  • 13
  • Why tag C++ and C++11 if you ask question about C? – Yksisarvinen Sep 04 '18 at 10:48
  • Show *all* the compilation commands, including the one for `main.c` (it might need `-rdynamic`). And your question is probably OS specific (perhaps a `linux` tag is missing). BTW, you could link more libraries into `libcombined.so` – Basile Starynkevitch Sep 04 '18 at 10:53
  • Show all command lines you use to build. – Maxim Egorushkin Sep 04 '18 at 11:37
  • @BasileStarynkevitch I can't link more libraries like protobuf and grpc as they are already provided as .so in /usr/local/lib. – Prasha Sep 04 '18 at 11:37
  • You don't link any library inside `libcombined.so` and perhaps you should (link the grpc library into it) – Basile Starynkevitch Sep 04 '18 at 11:39
  • @BasileStarynkevitch it will increase the library size even if I pass the library during the compilation as `gcc main.c -l:./libcombinedwrapper.so -l:/usr/local/lib/libgrpc.so -l:/usr/local/lib/libprotobuf.so -o main -ldl` It doesnot work. – Prasha Sep 04 '18 at 11:44
  • See [this](https://stackoverflow.com/a/19424604/841108) answer. Doing the same won't increase a lot your `libcombined.so`. I can't understand why you need a wrapper, and your question should give the code of `wrapper.cc`. Please provide some [MCVE] in your question – Basile Starynkevitch Sep 04 '18 at 11:50
  • I think he needs a wrapper since grpc functions are written in C++. – Prashant Shubham Sep 04 '18 at 12:00
  • Grpc library is in c++ and I need to call those function from my C code. – Prasha Sep 04 '18 at 12:02
  • @BasileStarynkevitch [link]https://stackoverflow.com/a/924181 refer this link. Combining already .so's is not possible on Unix. – Prashant Shubham Sep 04 '18 at 12:04
  • Have you ever considered to use [GNU make](https://www.gnu.org/software/make/manual/make.html#Simple-Makefile)? – KaiserKatze Sep 04 '18 at 12:47
  • @KaiserKatze how will make help with dynamic library linking? – Prasha Sep 04 '18 at 14:23

1 Answers1

0

g++ -shared -o libcombined.so *.o

You need to also link in all dependencies of the objects (libgrpc here).

You can add -Wl,--no-allow-shlib-undefined to verify that libcombined.so is linking everything it needs.

P.S. To avoid core dump, you should exit or return once dlopen fails.

P.P.S. It is generally a very bad idea(TM) to link *.o. Use proper Makefile to avoid unnecessary compilations and explicitly list objects that you are intending to put into libcombined.so.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362