how do I extend Lua with a static c++ library? - c++

I have a Visual Studio 2008 C++03 application that uses Lua 5.2.1. I would like to extend Lua with a module called "foo", but when I call require("foo") in my Lua script, I get the error:
foo_test.lua:1: module 'foo' not found:
no field package.preload['process']
no file '!\lua\process.lua'
no file '!\lua\process\init.lua'
no file '!\process.lua'
no file '!\process\
My Lua script:
foo.bar()
My lua_foo.h file:
#include <lua.h>
extern "C" int luaopen_foo( lua_State* L );
My lua_foo.cpp file:
#include "lua_foo.h"
#include <lua.hpp>
static int l_bar( lua_State *L )
{
puts( "in bar()" );
return 1;
}
int luaopen_foo( lua_State *L )
{
static const luaL_Reg foo[] = {
{ "bar", l_bar },
{ NULL, NULL }
};
luaL_newlib( L, foo );
return 1;
}
These are compiled in to a static library "lua_foo.lib" which is statically linked to my main Lua executable.
Can anybody help me understand where I'm going wrong? thanks. I would prefer to avoid c++ wrappers (for now) and I do not want to package this library as a separate DLL from the main Lua engine.
EDIT
The issue was in the lua engine code. I added the luaL_requiref per #NicolBolas 's suggestion.
lua_State* L = luaL_newstate();
if( NULL != L )
{
luaL_openlibs( L );
luaL_requiref( token.get(), "foo", luaopen_foo, 1 );
luaL_dofile( L, "foo_test.lua" );
lua_close( L );
}

It's important to understand how the require machinery works and therefore why your code doesn't.
require is designed to look for Lua scripts in the file system and DLLs. Static libraries are not DLLs; indeed, as far as C/C++ is concerned, once you've finished linking, static libraries are no different than compiling those .c/.cpp files into your application directly.
When require finds a DLL with the appropriate name, it loads it and attempts to find a function named luaopen_<modname>, where <modname> is the name of the module. When it does, it will execute this function and store the value it returns in an internal database of loaded modules.
Calling require for a module will return whatever this function returned; if the module has already been loaded, then the return value is pulled from the database and returned directly.
Simply calling luaopen_foo will not do any of this. Indeed, simply calling this function is a bad idea; it is a Lua function and needs to be called as a Lua function (ie: you need to push it onto the Lua stack with lua_pushcfunction and call it with lua_call and so forth).
If you want to create a local module (one not in a Lua script or DLL, but exposed from your code), then you need to use the Lua facilities to do that. Specifically, use luaL_requiref:
luaL_requiref(L, "foo", luaopen_foo, 0);
Call this instead of calling luaopen_foo directly. This will automatically register the return value from luaopen_foo with require's internal database of loaded modules. Thus, subsequent calls to require "foo" will return this table.
One more thing: do is a keyword in Lua; you should not use keywords for Lua table key names. You can, but you always have to quote them (ie: your script must do foo["do"](...) to call it).

luaopen_foo creates a table with one function in it, but it doesn't expose it to Lua in any way. You need to assign it to something your scripts can access if you want to access it. You can do this with the package mechanism, or just assign it to a global (which is what Lua's built-in libraries do).
You have a field named do, which is problematic if you want to use foo.do syntax, because do is a keyword.
The return value of a Lua function tells Lua how many values you left on the stack. Your l_do function lies with its return value.
In the case of luaopen_foo, since you're calling it directly and ignoring it's return value, there's no need for it to return anything at all.
Change your code to this:
static int l_bar( lua_State *L )
{
puts("l_bar called.");
return 0;
}
void luaopen_foo( lua_State *L )
{
static const struct luaL_Reg foo[] = {
{ "bar", l_bar },
{ NULL, NULL }
};
luaL_newlib( L, foo ); // create table containing `bar`
lua_setglobal(L, "foo"); // assign that table to global `foo`
}
And change your script to this:
foo.bar()

Related

Global variables missing after using require in lua

The problem is, a "require" keyword clears all global variables defined in the same file.
I am working on a project in c++. I use lua 5.3. The lua scripting style is:
1 all lua codes contains 1 common library file, and several small files each acting as a function.
2 when program start, the lua common library is compiled and executed, leave its global variables in the lua state. Then the small files are compiled not executed.
3 when program come to some point, relevant small lua file will be called(just as I say, every small file is a function). The global functions and variables defined in the common library will be used in the small lua file. That's why I compile and execute the common library when program start.
4 I'm very sure I only use 1 lua_State.
It worked fine, until I decide to split common library to multiple files, And use "require" in the main file. When program start, the main file will be compiled and executed.
Not a single code changed, just add come "require". Strange thing happened: All global variables and global functions are missing. When global function is called in small lua file, a "called a nil value" error raises.
I then make a experiment, I delete all "require" lines in the main library file, and it turns out that the global functions defined in the main library worked very well. I then require a empty file "simple.lua", the global functions defined in the main library was missing, cannot be called from the small lua file.
How to explain this? How can a "require" keyword clears all global variables defined in the same file?
in lua library:
require("simple")
function foo()
return 1+1
end
in lua small file
return foo()
result: attempt to call a nil value (global 'foo')
after delete "require", lua library:
function foo()
return 1+1
end
result: no error happens, 2 is returned
the c++ side code:
lua common library compile and excute:
int code = luaL_loadbuffer(L, s, strlen(s), "commonlib");
if(code != 0) {
std::string error = lua_tostring(L, -1);
lua_pop(L, 1);
return error;
}
code = lua_pcall(L, 0, 0, 0);
if(code > 0)
{
std::string ret = lua_tostring(L, -1);
lua_pop(L, 1);
return ret;
}
else
return ""; //empty string means no error
lua small function file compile:
int code = luaL_loadbuffer(L, s, strlen(s), "RULE1");
if(code != 0) {
std::string error = lua_tostring(L, -1);
lua_pop(L, 1);
return error;
}
else
{
return ""; //return empty means no error
}
The L in both code is the same lua state (or it won't work when "require" is removed). After compile, the small file function at the stack top is saved in global register with a reference variable "ref".
When call lua small file, the ref is pushed in the stack, a lua_pcall is used, nothing special.
Resolved the problem by myself.
Because of a duplicated copy/paste, the lua vm is created the second time afterwards. It's rather confusing because if there is no "require", everything is alright. It is a total coincidence.
All I learnt from this is: always double check the copy/paste code.

ffi namespace not found after calling luaopen_ffi

I have a C++ program that creates will create a lua_State and invoke custom lua code. Before calling the custom lua function, luaopen_ffi() is called with the lua_State:
luaopen_ffi(lua_state_);
However, when my program execute the custom lua code, it cannot find ffi. I further print out the value of ffi, and sadly it's nil instead:
print(ffi) --- which outputs nil
while other libraries loaded using luaopen does have a non-nil value, for instance
print(io) --- outputs table: 0x400af268
I further checked the source code of luaopen_ffi, it says it does not create a global ffi namespace based on its comment:
LUALIB_API int luaopen_ffi(lua_State *L) {
CTState *cts = lj_ctype_init(L);
settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1)));
cts->finalizer = ffi_finalizer(L);
LJ_LIB_REG(L, NULL, ffi_meta);
/* NOBARRIER: basemt is a GC root. */
setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
LJ_LIB_REG(L, NULL, ffi_clib);
LJ_LIB_REG(L, NULL, ffi_callback);
/* NOBARRIER: the key is new and lj_tab_newkey() handles the barrier. */
settabV(L, lj_tab_setstr(L, cts->miscmap, &cts->g->strempty), tabV(L->top-1));
L->top--;
lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */
lua_pushliteral(L, LJ_OS_NAME);
lua_pushliteral(L, LJ_ARCH_NAME);
LJ_LIB_REG(L, NULL, ffi); /* Note: no global "ffi" created! */
ffi_register_module(L);
return 1;
}
I also tried ffi = require("ffi") and it does not work :(.
So can I know how can I use ffi features after calling luaopen_ffi? Or luaopen_ffi is not the correct way?
If you want a global named ffi, try this:
luaopen_ffi(lua_state_);
lua_setglobal(lua_state_ ,"ffi");
It seems that luaopen_ffi leaves the table on the stack, as is usual in Lua modules.

Lua: fails to get field after loading a second string;

Good afternoon,
I am working on a LUA/C++ application, from which i need lua to be able to call other lua code recursively, e.g: C++ calls lua function, lua function calls another lua function from another string that is loaded using a registered C function that runs at the start of the first lua function;
here are the steps i am following:
lua_State* state = luaL_newstate();
luaL_openlibs(state);
lua_register(state, "secondLua", secondLua);
lua_getfield( _luaState, LUA_GLOBALSINDEX, "init" );
lua_pcall( _luaState, 0, 0, 0 );
int secondLua(lua_State* state){
char* myString[128] = "function init2()\n io.write(\"hello\")\n end";
luaL_loadstring(pLuaState, myString);
lua_getfield(pLuaState,LUA_GLOBALSINDEX, "init2"); // function init2 declared on myString
lua_pcall(pLuaState, 0, LUA_MULTRET, 0);
//getting "attempt to call a nil value" here
return 0;
}
Any help is appreciated, and second, i would like to know if there is a way i can name the second function "init" as well as the first one;
PS: I am using C++14 and lua 5.1 on LUAJIT, and i cant use lua's dofile;
lua_loadstring() compiles supplied source and puts Lua chunk on stack. It won't execute it though, so init2() still not defined when you expect that.
Replace lua_loadstring() with luaL_dostring() to actually run that chunk and define new lua functions. Or call lua_pcall() right after lua_loadstring(). Actually, luaL_dostring() does exactly that - lua_loadstring() followed by lua_pcall().

How to replace Lua default error print?

I'm implementing Lua as a script language into a Windows application. Due to the application's structure, printout isn't using streamed io, such as stdout and stderror.
I have managed to override the Lua print to fit into my structure...
lua_register(L,"print", cs_print);
...but how do I override all error an debug printouts without using streams? I need to handle this in a function (similar to print).
The only place where Lua writes to stderr is in the panic function that luaL_newstate installs. If you're embedding Lua into your application, make sure you start Lua from a protected call and no panic will ever occur. See http://www.lua.org/source/5.2/lua.c.html#main for ideas.
After a lot of Google I came up with this solution to fetch compiler and runtime error messages as well to redirect the standar Lua print function.
I use C++ Builder but I think it can be useful for anyone looking for the same answer.
The script is running in a TScriptLua object instance and to map a Lua state against the correct script instance, I use a std::map list to look up the object pointer.
// list for mapping Lua state with object pointers.
static std::map<lua_State*,TScriptLua*> LuaObjMap;
Next is an inline function to get the object pointer from a Lua state pointer.
extern "C" {
// Inline to map Lua state pointer to object pointer
static inline TScriptLua* GetScriptObject(lua_State* L) {
return LuaObjMap.find(L)->second;
}
This function will replace the standard Lua print function. The object pointer (f) has a member function in its base class called Out() that will output a char buffer in the associated window control.
// New Lua print function
static int cs_print (lua_State *L) {
// Map Lua state to object
TScriptLua* f = GetScriptObject(L);
if (f) {
int count = lua_gettop(L);
for (int i=1; i <= count; ++i) {
const char *str = lua_tostring(L, i); // Get string
size_t len = lua_rawlen(L,i); // Get string length
// Output string.
f->Out(str,len);
}
}
return 0;
}
This is my error print routine that will display the compiler/runtime error. As for the Lua print function, the f->Out is used again to print the error message.
// Error print routine
static int cs_error(lua_State *L, char *msg) {
// Map Lua state to object
TScriptLua* f = GetScriptObject(L);
// Get error message
AnsiString m = String(msg) + " " + String(lua_tostring(L, -1));
// "print" error message
f->Out(m.c_str(),m.Length());
// Clenaup Lua stack
lua_pop(L, 1);
return 0;
}
} // <--- End extern C
Here is the actual load and run member. After the new Lua state has been created it is associated with this object in the mapping list. Then it loads the script from a Rich edit control with luaL_loadbuffer(), checks for compiler errors and runs the compiled script with lua_pcall().
void __fastcall TScriptLua::Compile(void) {
// Create new Lua state
lua_State *L = luaL_newstate();
// Store mapping Lua state --> object
LuaObjMap.insert( std::pair<lua_State*,TScriptLua*>(L,this) );
// Override Lua Print
lua_register(L,"print", cs_print);
// Load and compile script
AnsiString script(Frame->Script_RichEdit->Text);
if (luaL_loadbuffer(L,script.c_str(),script.Length(),AnsiString(Name).c_str()) == 0) {
if (lua_pcall(L, 0, 0, 0)) // Run loaded Lua script
cs_error(L, "Runtime error: "); // Print runtime error
} else {
cs_error(L, "Compiler error: "); // Print compiler error
}
// Close Lua state
lua_close(L);
// Remove Lua --> object mapping
LuaObjMap.erase( LuaObjMap.find(L) );
}
This isn't my final solution, but it does the trick so far. I think the best thing is to write stream handling into the TScriptLua object so I can register it directly into Lua.

Add members dynamically to a class using Lua + SWIG

This Lua code, creates a table and dynamically adds a new member. Running this I can get "hello" on the screen as expected:
foo = {}
foo.x = "hello"
print(foo.x)
But now I'm using SWIG to bind some C++ classes to Lua.
For that purpose, in a test.i (SWIG module file) I created a simple class like this:
%module test
%inline
%{
class Foo
{
public:
Foo() { X = 0; }
void SetX(int x) { X = x; }
int GetX() { return X; }
private:
int X;
};
%}
Then I wrote a test Lua code like that:
obj = test.Foo()
obj:SetX(5)
print("Number: " .. obj:GetX())
Running and getting "Number 5" as expected. The problem is that when I dynamically add a new member to my SWIG-binded object, and I try to access it, like so:
obj.Y = 7
print("Number: " .. obj.Y)
I get this error message:
"attempt to concatenate field 'Y' (a nil value)"
Is it possible to dynamically add new members on objects binded using SWIG? Is there some option without having to move to another Lua binding library?
SWIG doesn't use tables for its objects; it uses userdata. After all, those objects are C++ objects, and need to store C++ data that Lua code shouldn't be able to touch.
And I wouldn't bother looking for "another Lua binding library"; pretty much all of them use userdata, which Lua code explicitly cannot modify (in order to provide the ability to do exactly this).
However, that doesn't mean you can't cheat.
You can always wrap the object you get from C++ code into your own Lua table, which would have a metatable that forwards unknown calls to the C++ object. The code to do so would look something like this:
local function WrapObject(cppObject)
local proxy = {}
local wrapper_metatable = {}
function wrapper_metatable.__index(self, key)
local ret = rawget(self, key)
if(not ret) then
ret = cppObject[key]
if(type(ret) == "function") then
return function(self, ...)
return ret(cppObject, ...)
end
else
return ret
end
else
return ret
end
end
setmetatable(proxy, wrapper_metatable)
return proxy
end
The returned proxy object is a Lua table that can have keys and values set on it. When you get a value, such as to call a function, it will see if that value was set in the table. If not, it attempts to fetch it from the C++ object that you wrapped, which will go through its metatable.
You'll need to expand this metatable if your C++ class uses other metafunctions like __add, __sub, __tostring and so forth.