1

I'm using a C library in my C++ project, which uses Cmake. In that project, I'm building a plugin from that library. During the development of the project, I used to add files like this to my plugin library in cmake:

add_library(plugin SHARED
    impl.cpp
    Interface.h
    ${LIBBTC_REPO}/src/base58.c
    ${LIBBTC_REPO}/src/bip32.c
    ${LIBBTC_REPO}/src/block.c
    ${LIBBTC_REPO}/src/ripemd160.c
    ...
    )

And everything was going fine. But after using the function ripemd160(), my shared library started giving an undefined symbol error:

plugin.so: undefined symbol: _Z9ripemd160PKhjPh

When studying the contents of the plugin with nm -g plugin.so | grep -i ripe, I got:

000000000002e1cb T ripemd160
                 U _Z9ripemd160PKhjPh

which shows that the original C function is not mangled and is not available, but C++ is expecting a mangled function name. That I don't understand.

What surprises me is that I also call other functions in other files. For example the function utils_hex_to_bin(), but I don't get that undefined symbol error there.

Why is C++ expecting this function to specifically be mangled, while all other C functions not? Is there a better way to do what I'm doing? Am I linking this incorrectly?

Btw, that file, ripemd160.c is the only file in the library that has the header file beside it, instead of being in the include directory. I don't know if that makes a difference.

I also tried creating another module for that library in CMake, but that doesn't help.

Please advise.


EDIT: Just to be clear, I never decalred any of the functions in the library. I just include headers from that library and that takes care of declarations. That's why I never mentioned extern "C".


Solved: Wrapping the include with extern "C" solved the problem. Apparently the library dev forgot to do that.

Cinder Biscuits
  • 4,880
  • 31
  • 51
The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189
  • 1
    The fact C++ expects a mangled name could be explained by a missing `extern "C"`. Probably due to a configuration error. – StoryTeller - Unslander Monica Jun 25 '18 at 11:43
  • It appears `ripemd160` isn't declared as `extern "C"` in your header file. Whatever C++ code is calling `ripemd160` needs to include a header that properly declares the function as `extern "C"`. – Andrew Henle Jun 25 '18 at 11:44
  • @StoryTeller But other files don't have `extern "C"` as well. The whole thing is a C library. Should I wrap the includes with `extern "C"` @Andrew ? – The Quantum Physicist Jun 25 '18 at 11:45
  • The other function is wrapped in `extern "C"`. That's what [`LIBBTC_BEGIN_DECL`](https://github.com/libbtc/libbtc/blob/79bede34866f958fc2f2a2fe04cf1dfd732ccd2e/include/btc/btc.h#L47) is for. – StoryTeller - Unslander Monica Jun 25 '18 at 11:47
  • And yup, as expected, [`ripemd160`](https://github.com/libbtc/libbtc/blob/dcb81761f9cd0bc52186e1fb09fdd4d2e9d4ee56/src/ripemd160.h) doesn't contain that wrapper. IDK if it's meant to be internal or not, but if it's just an oversight, you may be able to fix it and send the authors a pull request. – StoryTeller - Unslander Monica Jun 25 '18 at 11:49
  • @StoryTeller It may be internal. I'm not sure. It's the only function that has its header in `src`. I'll try the fix now. – The Quantum Physicist Jun 25 '18 at 11:51
  • @StoryTeller Wrapping the include with `extern "C"` fixed the issue. I'll be contacting the guy of the repo. Thanks for the help. – The Quantum Physicist Jun 25 '18 at 11:53
  • You use **internal header** of the C library implementation, and bet its author for the header not being prepared for C++, are you serious? – Tsyvarev Jun 25 '18 at 16:07
  • As for the question post, it lacks any concrete code. For 1-rep user this would end up in some downvotes and, possibly, close votes. But even after adding the code, the question would be a candidate for well-known duplicates, e.g. on https://stackoverflow.com/questions/3329159/including-c-headers-inside-a-c-program. Currently the question has some "the problem can no longer be reproduced" CV. Not sure what other CV means, but CV from me implied that you simply **forgot** `extern "C"` and want the question to be deleted after you reveal that. But now I am not quite sure... – Tsyvarev Jun 25 '18 at 16:17
  • @Tsyvarev I wasn't sure it's internal header. I don't deal with C that much, and given that other includes have worked with no mangling, I thought that the compiler is not mangling names because it's getting `.c` files instead of cpp. I didn't know that there was an extern C wrapping everything (as StoryTeller noticed). So, no, it's not "forgot `extern "C"`". And btw, there's code. I added links from github explaining the question. Some times having code is a burden and this happened here on SO many times. As long as people could help, the code is not necessary. Please, no dogma is necessary. – The Quantum Physicist Jun 25 '18 at 16:38
  • StoryTeller noted the macro, defined in "external" header `btc/btc.h` located in the `include/` directory and used by the headers in that directory and can be used by other projects freely. But you use header from `src/` directory, where implementation sources are located. It is usual convinience that such headers are internal for implementation and shouldn't be used outside. As for links to github instead of providing the code: links content could be removed or changed in the future, which will cause the question to be invalid. This is why the code is really necessary in you case. – Tsyvarev Jun 25 '18 at 16:53
  • @Tsyvarev How do you suggest to get all that code from github? Genuine question here. – The Quantum Physicist Jun 25 '18 at 17:34

1 Answers1

3

Try to declare the ripemd160() function with extern "C". Or you can do this simply by

extern "C" { #include "ripemd160.h" }

richq
  • 55,548
  • 20
  • 150
  • 144
Kevin Chen
  • 56
  • 4