DEV Community

Tenry
Tenry

Posted on

When your C++ code complains about undefined references

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.

Discussion (4)

Collapse
dynamicsquid profile image
DynamicSquid

Is extern "C" all you need to compile C code in C++? What about the C only features?

Collapse
tenry profile image
Tenry Author

I never had trouble with that approach in the past, and most C libraries I see I could also only spot the extern "C" thing (if __cplusplus is defined). Do you have any C specific features in mind that could not work?

Collapse
dynamicsquid profile image
DynamicSquid

I think variable length arrays are one

Collapse
epiccoderjit profile image
Sammo

This was quite informative for a beginner like me. Thanks.