Closed Memorix101 closed 8 years ago
You need make lua module. This is shared-object(UNIX) or DLL(Windows).
I'm wrote an example for module. https://github.com/satoren/kaguya/blob/ba1611a4d277825bccda0fdfbb8b0f9161cb6048/examples/hello_lua_module.cpp https://github.com/satoren/kaguya/blob/ba1611a4d277825bccda0fdfbb8b0f9161cb6048/examples/hello_lua_module_exec.lua
Thank you for the examples :)
Oh, what I meant was.
I have a main.lua file and I want to pass a module (example.lua) to it from inside my C++ code. Instead of writing require in my file. the reason why i want that is. I'm using a virtual file system and so I need to write an include function to do that. the default script linking from lua doesnt work, becasue it cant read the filesystem. So I wrote a function called include that first seeks if the lua file I want to include is existing and then I wanted to say the kaguya lib, hey mount that script and pass it to my main lua.
Here we are inside my virtual filesystem. There is my main lua script that gets mounted first. Next to it is another lua script with another functions and stuff in it. I need to link both, but cant use 'require' or packages to do, because my filesystem is an encrypted file only my c++ code can read and write to.
C++ Code exmaple
int include_module(const char* t)
{
if (PHYSFS_exists(t))
{
std::cout << t << " LUA FOUND" << std::endl;
std::stringstream sstream;
PhysFS::ifstream m(t);
std::string mtemp((std::istreambuf_iterator<char>(m)), std::istreambuf_iterator<char>());
//Kaguya needs to link the found script here to my main script
}
else
{
std::cout << "INCLUDE " << t << " NOT FOUND" << std::endl;
}
return 0;
}
int include_module(lua_State* L)
{
kaguya::State state(L);
const char* t = lua_tostring(L,1);//get first arguments
//load data.
state.dostream(stream); or state.dostring(luacode);
}
or
kaguya::LuaCodeChunkResult include_module(const char* t)
{
//load data
return kaguya::LuaCodeChunkResult(luacode)://Execute lua code, and return value from that.
}
Well, that's still not linking the other lua file with my main file.
Another try to explain:
int include { //include external lua file to extend main file }
int main() { //loads vfs //loads main.lua as stream //loads included lua files catched by include module function before }
my code looks like that:
int include_module(const char* t)
{
//load data
if (PHYSFS_exists(t))
{
std::cout << t << " LUA FOUND" << std::endl;
std::stringstream sstream;
PhysFS::ifstream m(t); //mounts the declared "t" file as stream within the vfs
std::string mtemp((std::istreambuf_iterator<char>(m)), std::istreambuf_iterator<char>());
//includede lua file
state.dostream(sstream); // i think this is still wrong :P
}
else
{
std::cout << "INCLUDE " << t << " LUA NOT FOUND" << std::endl;
}
return 0;
}
int main(int argc, char* argv[])
{
...
PHYSFS_mount(mountFile, NULL, 1); // ROM file //For details on(arg, NULL, 1) read
int hasMain = PHYSFS_exists("main.lua");
if (hasMain != 1)
mounted = false;
if (mounted)
{
kaguya::LoadLibs();
//register modules
luaopen_graphics(state);
luaopen_audio(state);
luaopen_system(state);
luaopen_input(state);
state.setErrorHandler(HandleError);
std::stringstream sstream;
PhysFS::ifstream m("main.lua"); mounts the main.lua file as stream within the vfs
std::string mtemp((std::istreambuf_iterator<char>(m)), std::istreambuf_iterator<char>());
sstream << mtemp;
mstream = mtemp; // Debug stuff for console
state.loadstream(sstream); // That loads main.lua first
state["include"] = &include_module; //here gets all other files included to extend my main lua
...
return 0;
}
In lua code :
require "stuff.lua" --this will pull an error because of the vfs
include_module("stuff.lua") --this is our c++ function declared above to include the required lua file from within the vfs
lua bla bla bla
Where do you define for state? and Where do you execute the main.lua?
This is totally off the topic, but kaguya::LoadLibs();
is do nothing.
State is defined in main.h and dofile is defined some later after checking some more stuff, but I think this is not case related.
That's what I want to do in Kaguya http://stackoverflow.com/questions/4525757/embedded-lua-loading-modules-programatically-c
Ok found out how I can do it.
main.cpp
kaguya::State state;
int include_module(const char* t)
{
//load data
if (PHYSFS_exists(t))
{
std::cout << t << "FOUND" << std::endl;
std::stringstream some_stream;
PhysFS::ifstream some_input(t);
std::string this_mtemp((std::istreambuf_iterator<char>(some_input)), std::istreambuf_iterator<char>());
some_stream << this_mtemp;
state.dostream(some_stream);
}
else
{
std::cout << t << " NOT FOUND" << std::endl;
}
return 0;
}
int main()
{
std::stringstream sstream;
PhysFS::ifstream m("main.lua");
std::string mtemp((std::istreambuf_iterator<char>(m)), std::istreambuf_iterator<char>());
state["include"] = &include_module;
sstream << mtemp;
state.dostream(sstream )
while(true)
{
// SDL DRAW STUFF OR WHATEVER
}
retrun 0;
}
main.lua
include("test.lua")
print("meep meep")
stuffinstuff()
test.lua
function stuffinstuff()
print("this is stuff")
end
Done, wow. I thought I need to register it as a Lua Lib or Lua Table.
Did you know instance or scope?
int main()
{
kaguya::State state;
{
kaguya::State state;
state["value"] = 1;
state.dostring("assert(value == 1)"); //pass
}
state.dostring("assert(value == nil)"); //pass
}
//in C
lua_getfield (L, LUA_GLOBALSINDEX, "require"); // function
lua_pushstring (L, "funky"); // arg 0: module name
err = lua_pcall (L, 1, 1, 0);
lua_setfield (L, LUA_GLOBALSINDEX, "funky");
equal to
-- in lua
funky = require ("funky")
equal to
//in C++ with Kaguya
state["funky"] = state["require"]("funky");
I'm wrote example.
int include_module(lua_State* L)
{
kaguya::State state(L);
const char* t = lua_tostring(L,1);//get first arguments`
but you write
int include_module(const char* t)
{
Why?
I told you that my lua scripts are inside a virtual filesystem. Lua itself can't find other scripts inside that (because of encryption, it shows a nil error), so I need the vfs to check if the needed file is existing. If existing the vfs needs to save it to memory and stream it.
using namespace kaguya;
State state;
void bad_function(const char* t)
{
state["value"] = t;//assigned to line:2 state
}
void good_function(lua_State* L)
{
State state(L);
const char* t = lua_tostring(L,1);
state["value"] = t;
}
int main()
{
State state;
state["bad_function"] = &bad_function;
state["good_function"] = &good_function;
state.dostring("bad_function('test')");
state.dostring("assert(value == nil)");//not assigned
state.dostring("good_function('test')");
state.dostring("assert(value == 'test')");//pass
}
Your implement is bad_function.
Are you sure ?
Why can I call this only once ? (I'd like to replace my current implementation with this one)
int include_module_L(lua_State* L)
{
kaguya::State state(L);
const char* t = lua_tostring(L, 1);
//state["value"] = t;
state["require"](t);
//or
state[t] = state["require"](t);
return 0;
}
require ("stuff") --one require call works
require ("stuff") --two doesn't
require ("another") --this is nil somehow
I'm sorry for my miss.
int good_function(lua_State* L)
{
State state(L);
const char* t = lua_tostring(L,1);
state["value"] = t;
return 0;
}
Please read lua document for require. http://www.lua.org/manual/5.3/manual.html
Ah, ok.
For my case this works:
local Aname = require "stuff"
local Bname = require "another"
but normally this works, too
require "stuff"
require "another"
print("meep meep")
stuffinstuff()
moarstuff()
wtf .. this implementation works inside the vfs without mounting the lua files first :o
int include_module_L(lua_State* L)
{
kaguya::State state(L);
const char* t = lua_tostring(L, 1);
state[t] = state["require"](t);
return 0;
}
It works for
local Aname = require "stuff"
local Bname = require "another"
and
require "stuff"
require "another"
Totally unexpected :o
@satoren So the working example would be:
using namespace kaguya;
int good_function(lua_State* L)
{
State state(L);
const char* t = lua_tostring(L,1);
state["value"] = t;
return 0;
}
int main()
{
State state;
state["good_function"] = &good_function;
state.dostring("good_function('test')");
state.dostring("assert(value == 'test')");//pass
}
Is this correct? Why is the return value required here? Is there any documentation on using functions taking a lua_state*
with kaguya? From the current readme I would have expected the void-function to work.
I'm sorry, it is not documented.
typedef int (*lua_CFunction) (lua_State *L);
defined in plain Lua.
And it is specialized in kaguya, it mean direct call from Lua VM.
Ah ok. Could you add that explanation somewhere? Also: How come the function got matched, although the return value was wrong? Shouldn't that be an error? If not, could you make it one so no one else falls into this trap?
use static_cast?
state["f"] = static_cast<lua_CFunction>(&f);
No, I mean, Why does this work?:
void wrongSig(lua_State* L){}
state["wrongSig"] = &wrongSig;
I think this should throw a compile time error because it is NOT a lua_CFunction
or be wrapped in kaguya so you don't need the return value.
Why does this work?:
lua_State*
is same type of coroutine.
void coroutine_receive_fn(lua_State* co){
lua_resume(co,0,0);
}
state["coroutine_receive_fn"] = &coroutine_receive_fn;
coroutine_receive_fn( coroutine.create(function () return 1 end) )
Do you think how should divide?
OK. lua_CFunction specialization is removed.
state["f"] = kaguya::luacfunction(&plain_lua_cfunction);//directcall by lua
state["corfn"] = kaguya::function(&plain_lua_cfunction);//int (coroutine) function(wrapped by kaguya)
state["corfn2"] = &plain_lua_cfunction;//int (coroutine) function(wrapped by kaguya)
Hey, I'm currently trying to understand "newLib". I want to register a lua script from inside my C++ code for my main lua script I load with dofile. :)
An example would be great :)
Thank you :D