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;
}
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
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"
}
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
__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.
Top comments (4)
Is
extern "C"
all you need to compile C code in C++? What about the C only features?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?I think variable length arrays are one
This was quite informative for a beginner like me. Thanks.