Reputation: 1521
I have a file configuration.cpp:
#include "configuration.hpp"
struct game_config* get_game_config(lua_State *L, char* script)
{
debug("Attempting to load configuration from %s", script);
// Execute the script
luaL_dofile(L, script);
// The environment should now be prepped, we can get the config variables
struct game_config* game_config;
lua_getglobal(L, "WINDOW_WIDTH");
game_config->screen_width = lua_tointeger(L, -1);
lua_getglobal(L, "WINDOW_HEIGHT");
game_config->screen_height = lua_tointeger(L, -1);
lua_getglobal(L, "GAME_TITLE");
game_config->game_title = lua_tostring(L, -1);
debug("Loaded config for %s, at %dx%d", game_config->game_title, game_config->screen_width, game_config->screen_height);
return game_config;
};
which includes configuration.hpp:
#ifndef CONFIGURATION_HPP_INCLUDED
#define CONFIGURATION_HPP_INCLUDED
#include "common.hpp"
#include "scripting.hpp"
// Data structures
struct game_config {
int screen_width;
int screen_height;
const char *game_title;
};
/*
* get_config
* run a script and retrieve configuration data from it
*/
struct game_config *get_game_config(lua_State*, char *);
#endif // CONFIGURATION_HPP_INCLUDED
which includes scripting.hpp
, in which the following lines import Lua5.2:
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
When I add those lines to configuration.cpp, the program compiles and runs. However, when they are in any other file (configuration.hpp, scripting.hpp) it does not:
||=== Build: debug in rpfreedom (compiler: GNU GCC Compiler) ===|
src/configuration.cpp||In function ‘game_config* get_game_config(lua_State*, char*)’:|
src/configuration.cpp|13|warning: ‘game_config’ is used uninitialized in this function [-Wuninitialized]|
src/main.cpp||In function ‘int main()’:|
src/main.cpp|13|warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]|
build/debug/configuration.o||In function `get_game_config(lua_State*, char*)':|
/home/leo/projects/rpfreedom/src/configuration.cpp|7|undefined reference to `luaL_loadfilex(lua_State*, char const*, char const*)'|
/home/leo/projects/rpfreedom/src/configuration.cpp|7|undefined reference to `lua_pcallk(lua_State*, int, int, int, int, int (*)(lua_State*))'|
/home/leo/projects/rpfreedom/src/configuration.cpp|12|undefined reference to `lua_getglobal(lua_State*, char const*)'|
/home/leo/projects/rpfreedom/src/configuration.cpp|13|undefined reference to `lua_tointegerx(lua_State*, int, int*)'|
/home/leo/projects/rpfreedom/src/configuration.cpp|14|undefined reference to `lua_getglobal(lua_State*, char const*)'|
/home/leo/projects/rpfreedom/src/configuration.cpp|15|undefined reference to `lua_tointegerx(lua_State*, int, int*)'|
/home/leo/projects/rpfreedom/src/configuration.cpp|16|undefined reference to `lua_getglobal(lua_State*, char const*)'|
/home/leo/projects/rpfreedom/src/configuration.cpp|17|undefined reference to `lua_tolstring(lua_State*, int, unsigned long*)'|
build/debug/scripting.o||In function `scripting_init()':|
/home/leo/projects/rpfreedom/src/scripting.cpp|7|undefined reference to `luaL_newstate()'|
/home/leo/projects/rpfreedom/src/scripting.cpp|20|undefined reference to `lua_settop(lua_State*, int)'|
build/debug/scripting.o||In function `scripting_report_errors(lua_State*, int)':|
/home/leo/projects/rpfreedom/src/scripting.cpp|30|undefined reference to `lua_tolstring(lua_State*, int, unsigned long*)'|
/home/leo/projects/rpfreedom/src/scripting.cpp|31|undefined reference to `lua_settop(lua_State*, int)'|
build/debug/scripting.o:(.rodata+0x88)||undefined reference to `luaopen_base(lua_State*)'|
Makefile|203|recipe for target 'bin/debug/rpfreedom' failed|
Makefile|160|recipe for target 'debug' failed|
||=== Build failed: 15 error(s), 2 warning(s) (0 minute(s), 1 second(s)) ===|
Obviously, the inclusion of configuration.hpp works, because there are no errors regarding the game_config struct, which is defined there; ditto for recursive includes, since the debug() macro follows the path debug.hpp -> common.hpp -> configuration.hpp -> configuration.cpp
. So, why are the #includes for the Lua header files not working in a similar fashion?
I decided to investigate; I ran g++ -Iinclude -I/usr/include/lua5.2 -E src/configuration.cpp| grep lua_getglobal
to view the preprocessor output, and it turns out that... they are. Along with its uses in the source code, that command returns:
extern void (lua_getglobal) (lua_State *L, const char *var);
So, I have no idea what is going on.
EDIT: Turns out that I have to do extern C {}
around my #include
s for Lua. However, now, only in configuration.hpp (not in scripting.hpp, where the Lua headers are included) I am getting another error:
include/configuration.hpp:21:37: error: ‘lua_State’ was not declared in this scope
struct game_config *get_game_config(lua_State*, char *);
However, the use of lua_State in scripting.cpp and scripting.hpp is not affected.
EDIT 2: Apparently the recommended way to embed Lua 5.2 is to compile it with your project, because it is very small, so I did so. However, even though the link command that my Makefile generates clearly links all my object files with the Lua object files:
g++ build/release/configuration.o build/release/lua5.2.4/lparser.c.o build/release/lua5.2.4/lcode.c.o build/release/lua5.2.4/lundump.c.o build/release/lua5.2.4/lzio.c.o build/release/lua5.2.4/ldo.c.o build/release/lua5.2.4/lapi.c.o build/release/lua5.2.4/lgc.c.o build/release/lua5.2.4/lfunc.c.o build/release/lua5.2.4/ldump.c.o build/release/lua5.2.4/ltable.c.o build/release/lua5.2.4/lcorolib.c.o build/release/lua5.2.4/loslib.c.o build/release/lua5.2.4/liolib.c.o build/release/lua5.2.4/ltm.c.o build/release/lua5.2.4/lmem.c.o build/release/lua5.2.4/lctype.c.o build/release/lua5.2.4/lauxlib.c.o build/release/lua5.2.4/ldebug.c.o build/release/lua5.2.4/lobject.c.o build/release/lua5.2.4/loadlib.c.o build/release/lua5.2.4/linit.c.o build/release/lua5.2.4/lmathlib.c.o build/release/lua5.2.4/llex.c.o build/release/lua5.2.4/lstate.c.o build/release/lua5.2.4/lopcodes.c.o build/release/lua5.2.4/lstrlib.c.o build/release/lua5.2.4/lbaselib.c.o build/release/lua5.2.4/ltablib.c.o build/release/lua5.2.4/ldblib.c.o build/release/lua5.2.4/lbitlib.c.o build/release/lua5.2.4/lvm.c.o build/release/lua5.2.4/lstring.c.o build/release/scripting.o build/release/main.o -L/usr/lib/x86_64-linux-gnu -Lm -Ldl -lsfml-graphics -lsfml-window -lsfml-audio -lsfml-network -lsfml-system -o bin/release/rpfreedom
I am getting the same linker errors I was getting earlier.
Does the order of arguments to the linker matter?
Upvotes: 3
Views: 1282
Reputation: 1521
I finally corrected this issue by compiling a static Lua myself (liblua.a
), creating a lib/ directory, and adding -Llib -llua
to my linker line. This will require additional effort to make cross-platform, but for now, it's fine.
Upvotes: 0
Reputation: 575
Well, your first warning is exactly what the compiler is telling you. Your code is this:
// The environment should now be prepped, we can get the config variables
struct game_config* game_config;
lua_getglobal(L, "WINDOW_WIDTH");
game_config->screen_width = lua_tointeger(L, -1);
and the warning is:
‘game_config’ is used uninitialized in this function.
You haven't set the pointer game_config
to point to anything before you access screen_width
on it. Maybe you need to set it to new game_config()
. I would prefer to make one on the stack and return it by value:
game_config config;
lua_getglobal(L, "WINDOW_WIDTH");
config.screen_width = lua_tointeger(L, -1);
...
return config;
Either way, it's probably better to make game_title a std::string
rather than a const char *
.
Upvotes: -1
Reputation: 118340
The error messages you've shown appear to come from your linker, not the compiler.
Everything was successfully included. Everything was successfully compiled. But the link failed, because some required library wasn't linked with.
Note that the error messages reference:
build/debug/configuration.o
...
build/debug/scripting.o
...
... and not your source code (the mentions of the cpp in the errors are misleading, they are really extracted from the debug information in your .o files). And the error messages are typically the error messages that come out of the linker.
Your source code is fine. You need to fix your makefile.
Upvotes: 2