When your C++ code complains about undefined references

Tenry - Dec 9 '20 - - Dev Community

Usually, when you compile and link your code and your compiler complains about undefined references, you check which references are missing and usually quickly find out which library you forgot to link.

Today, however, I encountered a strange issue where the compiler complained even though the (static) library, which provides the symbols in question, was clearly added to the command line that links the final binary. So what was going on?

In my specific case, I built the Lua library, and got some files in the end, including some header files like lua.h or lauxlib.h and of course the liblua.a. I wrote some basic code to verify that Lua is actually working. Following some quickstart tutorial on the internet, my C++ code somewhat looked like this:

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

int main(int argc, char **argv) {
  lua_State *L;
  L = luaL_newstate();
  luaopen_base(L);

  luaL_loadstring(L, "(some lua code)");

  // and so on...

  return 0;
}
Enter fullscreen mode Exit fullscreen mode

I put everything in a CMake file, compiled and bam, undefined references. I enabled verbose output to verify it's actually linking the liblua.a file. I verified it's the right location and the file actually exist.

Didn't I compile the Lua library correctly? Were the symbols in question missing? Using nm showed me that the symbols in questions are there:

$ nm liblua.a | grep luaL_loadstring
0000000000002d60 T luaL_loadstring
Enter fullscreen mode Exit fullscreen mode

So, why does it complain? It took like like half an hour to figure out where the issue is.

The solution

The issue is C++. C++ uses name mangling which differs from the generated names in C. Lua is a C library and I compiled it as C. Since I include the C header file lua.h in a C++ file, it's treated as C++ code, hence the compiler is looking for C++ names.

Luckily, Lua also provides a C++ header file, lua.hpp. I replaced my #include <lua.h> by #include <lua.hpp> and et voilà, it works!

What does lua.hpp actually do? Not much:

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
Enter fullscreen mode Exit fullscreen mode

If you have some experience with coding in C++, you might already have used other C libs, also simply #include <somelib.h>, without having any issues. So, what do others do? Checking the C header file of another lib, the outline looks like this:

#ifdef __cplusplus
extern "C" {
#endif

// all the declarations go here

#ifdef __cplusplus
}
#endif
Enter fullscreen mode Exit fullscreen mode

__cplusplus is only defined if this file is processed as a C++ file. For some reason, the lua.h file does not do that, so that's why they provided a dedicated C++ header file.

. . . . . . . .
Terabox Video Player