Redirecting/redefining print() for embedded Lua - c++

I have embedded Lua in my C++ application. I want to redirect print statements (or maybe simply redefine the print function?), so that I can display the evaluated expression somewhere else.
What is the best way to do this: redirect or redefining the print() function?
Any snippets/pointers to snippets that show how to do this would be much appreciated.

You can redefine the print statement in C:
static int l_my_print(lua_State* L) {
int nargs = lua_gettop(L);
for (int i=1; i <= nargs; i++) {
if (lua_isstring(L, i)) {
/* Pop the next arg using lua_tostring(L, i) and do your print */
}
else {
/* Do something with non-strings if you like */
}
}
return 0;
}
Then register it in the global table:
static const struct luaL_Reg printlib [] = {
{"print", l_my_print},
{NULL, NULL} /* end of array */
};
extern int luaopen_luamylib(lua_State *L)
{
lua_getglobal(L, "_G");
// luaL_register(L, NULL, printlib); // for Lua versions < 5.2
luaL_setfuncs(L, printlib, 0); // for Lua versions 5.2 or greater
lua_pop(L, 1);
}
Since you are using C++ you'll need to include your file using 'extern "C"'

You can simply redefine print from a Lua script.
local oldprint = print
print = function(...)
oldprint("In ur print!");
oldprint(...);
end

See luaB_print in lbaselib.c. The comment there reads:
/* If you need, you can define your own `print' function, following this
model but changing `fputs' to put the strings at a proper place (a
console window or a log file, for instance). */
You can just edit that function or define a new one. This has the advantage of being simple and portable, but it won't handle io.write (which you may or may not care about).
Redirecting IO isn't going to be platform specific (such as SetStdHandle in Windows), but will take care of print and io.write without redefining either.

Write your own C or Lua function and redefine print.

You can just redefine the following macros:
lua_writestring
lua_writeline
lua_writestringerror
to whatever you like.
I'm not sure about the lua version where this was introduced - but it works in 5.3 for me.
Check your lauxlib.h or luaconf.h.

Related

LUA & C++: How to properly use C++ function inside LUA's code

I'm currently learning using LUA in C++ code. And I came to a point where I cannot figure out how to use C++ function in LUA's code.
I want to create simple function in c++ and then use it in LUA.
My approach is as follows (taken from some tutorials):
In main.cpp:
void write(const char* str) {
std::cout<<str<<std::endl;
}
static int l_write(lua_State* L) {
const char* str = lua_tostring(L, 1); // get function argument
write(str); // calling C++ function with this argument...
return 0; // nothing to return!
}
int main(){
lua_State* L = luaL_newstate();
luaL_openlibs(L); // load default Lua libs
if (luaL_loadfile(L, "test.lua")) {
std::cout<<"Error loading script"<<std::endl;
}
lua_pushcfunction(L, l_write);
lua_setglobal(L, "write"); // this is how function will be named in Lua
lua_pcall(L, 0, 0, 0); // run script
}
and in test.lua I've got:
write("Hello, world!")
write("The square root of 2 is "..math.sqrt(2))
x = 42
write("We can use variables too, x = "..x)
The problem appears in the very beginning of this code: I cannot even a load script luaL_loadfile(L, "test.lua") returns value 7 (which is as I checked NIME_AGAIN 7 /* temporarily out of resources */).
Everything else works just fine do provided I don't use my custom c++ functions. I can load values from LUAs file normally, can execute function ect.
I suppose that LUA after reading file already compiles it and then finds out name of function that does not exist, namely "write" and returns error in case of reading this file, is it possible? And if so how to resolve this problem, and how to use this feature correctly?
Mhm, guys. It is strange but I did lua_pop(L, 1) once, run and then delete it and now its working just fine O.o

How to properly read string and table arguments with Lua c API?

I spent few hours trying to make it work without success. I have a C++ program with function exposed to Lua script. Lua script uses it like this:
setData('type', {a=1, b=2, c=3})
So first argument is string and second is table.
My current and best version of C++ setData function looks like this:
string sType;
map<string, uint8_t> mOptions;
int nArgs = lua_gettop(i_pState);
if (nArgs == 2)
{
if (lua_isstring(i_pState, 1) != 0)
sType = lua_tostring(i_pState, 1);
if (lua_istable(i_pState, 2) != 0)
{
lua_pushnil(i_pState);
while(lua_next(i_pState, 2))
{
uint8_t nValue = uint8_t(lua_tonumber(i_pState, -1));
string sKey = lua_tostring(i_pState, -2);
mOptions[sKey] = nValue;
lua_pop(i_pState, 1);
}
lua_pop(i_pState, 1);
}
}
return 0;
It works fine but causes "program.exe has triggered a breakpoint" error afterwards at the end when lua_close() function called.
What is wrong with this code?
UPD1. I'm not getting error without handling second argument.
UPD2. My code behaves very strangely. I think it could be issue of mixing extern "C" and C++ code.
UPD3. Turns out this is heap corruption. I can't understand where is cause. Probably this is not related to lua at all.
Finally! Recompilation of Lua code as C++ code didn't work (positive thing is I don't have to worry about extern "C" anymore). But I found two redundant lua_pop() calls. I removed them and now it works fine.
I didn't expect Lua to be so dangerous!

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.

SWIG Lua: Extending (%extend) class with %native. Is it possible to add %native method?

%module test
class Foo{
public:
Foo();
}
I want to have something like this:
%extend Foo{
%native(Bar) int Bar(lua_State * L);
}
In the .i file for your bindings, at the end include this code:
%wrapper %{
// This is code to add a new function to the object's metatable
void script_addNativeMethod(lua_State *L, const char *className, const char *methodName, lua_CFunction fn)
{
SWIG_Lua_get_class_registry(L); /* get the registry */
lua_pushstring(L, className); /* get the name */
lua_rawget(L,-2); /* get the metatable itself */
lua_remove(L,-2); /* tidy up (remove registry) */
// If the metatable is not null, add the method to the ".fn" table
if(lua_isnil(L, -1) != 1)
{
SWIG_Lua_get_table(L, ".fn");
SWIG_Lua_add_function(L, methodName, fn);
lua_pop(L, 2); /* tidy up (remove metatable and ".fn" table) */
}
else
{
printf("[script_addNativeMethod(..)] - \"%s\" metatable is not found. Method \"%s\" will not be added\n", className, methodName);
return;
}
}
%}
What this does is adds a new function to the wrapper CPP file called "script_addNativeMethod". You can call this function in the "init" binding code like so:
// Wrapper to add native Lua methods to existing C++ classes
%init %{
script_addNativeMethod(L, "MetatableName", "methodName", /*int function(lua_State *L)*/function);
%}
Above all this, in the binding file you need to have the actual native lua function that you want to use as a method of your userdata:
%{
int function(lua_State *L)
{
printf("Method called!\n");
return 0;
}
%}
I practically just figured this out, and I wanted to post it here because this page ranks high in google and this is a pretty decent solution to get the job done. This needs to be done in every wrapper binding (*.i) file that you write with SWIG.
Good luck!
Lua does not have any true concept of method, just of tables of functions with some syntactic sugar so you can write Lua code that looks quite OO'ish:
foo = test.Foo() # will call the C++ Foo constructor and return a wrapped (Lua) Foo
myInt = foo:Bar()
When you write
myInt = foo:Bar()
Lua is actually executing
myInt = foo.Bar(foo)
which will cause Lua to look in the foo metatable for a function called Bar and will give it the foo instance as first parameter. Therefore what you would have to do is more along the lines of the following pseudocode (not tested, there are likely syntax errors, wrong order of parameters etc but hopefully you get the idea):
%native(Bar) int Bar(lua_State * L);
%{
int Bar(lua_State*L) {
// there should be one arg on the stack: the Foo instance
Foo* foo = (Foo*)<get void* from L stack>
int answer = foo.Bar();
// push answer onto L stack
lua_pushnumber(L, answer);
return 1;
}
%}
%luacode {
test.Foo.Bar = test.Bar
}
...
%}
The %luacode makes Bar available as part of Foo "class", although I'm a little rusty in that area, you might have to add Bar the the Foo metatable instead, or do it from C (see section 5.6 of the SWIG user guide for sections of .i file where you could try to do this).
Curious to know if that works.

How to overload printf or cout

I use cout statements in my program for debugging purposes. I would like to make a function that works like it, or works like printf, but is sensitive to a global variable. If this global variable is true, then it will print to screen. If it is false, then it won't print anything. Is there already a function like this? If not, then how can it be made?
Something like this:
int myPrintf(const char* format, ...)
{
if (globalCheck == 0)
return 0
va_list vl;
va_start(vl, format);
auto ret = vprintf(format, vl);
va_end(vl);
return ret;
}
va_start and va_end take the arguments in the ... and encapsulate them in a va_list. with this va_list you can then the vprintf which is a variant of printf designed exactly for this need.
Side note - usually it is bad practice to use global variables. A better thing to do is to encapsulate it in a class like this -
class ConditionalPrinter {
public:
ConditionalPrinter() : m_enable(true) {}
void setOut(bool enable) { m_enable = enable; }
int myPrintf(const char* format, ...);
private:
bool m_enable;
}
and then to check m_enable instead of the global variable.
Usage of this looks like this:
ConditionalPrinter p;
p.myPrintf("hello %d", 1); // printed
p.setOut(false);
p.myPrintf("hello2 %d", 1); // not printed
....
Don't write it yourself. Doing it right is much harder then you think. Even harder when you need threads and efficiency. Use one of existing logging libraries like:
glog: http://code.google.com/p/google-glog/ (I prefer this - it is lightweight and do what it needs to do)
Log4cpp http://log4cpp.sourceforge.net/ (powerful and configuration compatible with popular java logging)
... add your favorite to this wiki
As someone else said, there are several good logging frameworks available. However, if you want to roll your own, the first thing to note is that cout isn't a function, it's a stream. The function is operator<<. What you can do is something like the following:
/* trace.h */
extern ostream debug;
void trace_init();
void trace_done();
/* trace.cpp */
#include "trace.h"
ostream debug(cout.rdbuf());
static ofstream null;
void trace_init()
{
null.open("/dev/null");
if(output_is_disabled) { // put whatever your condition is here
debug.rdbuf(null.rdbuf());
}
}
void trace_done()
{
null.close();
}
You might have to adjust a bit if you're on a platform without /dev/null. What this does is let you write
debug << "here's some output << endl;
and if you have the output enabled, it will write to cout. If not, it will write to /dev/null where you won't see anything.
For that matter, you could just set cout's rdbuf to somewhere where you won't see that output, but I would find that to be a really bad idea. Creating new streams gives you a lot more flexibility in controlling your output.