LuaLanes / lanes

Lanes is a lightweight, native, lazy evaluating multithreading library for Lua 5.1 to 5.4.
Other
465 stars 96 forks source link

Can't seem to get lua lanes to work properly when embedded #109

Closed anfractuosity closed 5 years ago

anfractuosity commented 10 years ago
#include <stdio.h>
#include "luajit.h"
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "lanes.h"
lua_State* L;

int load_lanes_lua( lua_State* L)
{
    luaL_dofile( L,"l.lua");
}

int main ( int argc, char *argv[] )
{
    L = luaL_newstate();
    luaL_openlibs(L); /* Load Lua libraries */
    luaopen_lanes_embedded( L, load_lanes_lua);
    lua_pop( L, 1);

    luaL_dostring(L,"local lanes = require 'lanes'.configure{with_timers = false};");   
    printf("%s\n",lua_tostring(L,-1));

    lua_close(L);

    return 0;
}

l.lua is actually lanes.lua

Gives me the error:

[string "local lanes = require 'lanes'.configure{with_..."]:1: module 'lanes' not found:
    no field package.preload['lanes']
    no file './lanes.lua'
    no file '/usr/local/share/luajit-2.0.3/lanes.lua'
    no file '/usr/local/share/lua/5.1/lanes.lua'
    no file '/usr/local/share/lua/5.1/lanes/init.lua'
    no file './lanes.so'
    no file '/usr/local/lib/lua/5.1/lanes.so'
    no file '/usr/local/lib/lua/5.1/loadall.so'
anfractuosity commented 10 years ago

Manged to get it to work using a different technique
https://github.com/anfractuosity/ipsum/blob/master/src/ipsum.c

However is there a a way to avoid having to use a C function for on_state_create, to load lua sockets.core. Can lanes not load it itself? As when I run lua ipsum.lua without on_state_create it works fine, I only have to use it, when I embed lanes in C.

local lanes = require "lanes".configure{ with_timers = false,protect_allocator = true,on_state_create = luaopen_mymodule}

anfractuosity commented 10 years ago

I've tracked it down to the following code in tools.c. For some reason lua_isfunction returns 0, for package/preload/socket.core

                case eLM_LaneBody:                                                                                                                     
                case eLM_FromKeeper:                                                                                                                   
                lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_REGKEY);                                 // {}                                             
                ASSERT_L( lua_istable( L2, -1));                                                                                                       
                lua_pushlstring( L2, fqn, len);                                                      // {} "f.q.n"                                     
                lua_rawget( L2, -2);                                                                 // {} f                                           
                if( !lua_isfunction( L2, -1))                                                                                                          
                {                                                                                                                                      
                        char const* from, * to;                                                                                                        
                        lua_getglobal( L, "decoda_name");                    // ... f ... decoda_name                                                  
                        from = lua_tostring( L, -1);                                                                                                   
                        lua_getglobal( L2, "decoda_name");                                                 // {} f decoda_name                         
                        to = lua_tostring( L2, -1);                                                                                                    
                        // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error 
                        (void) luaL_error( (mode_ == eLM_FromKeeper) ? L2 : L, "%s: function '%s' not found in %s destination transfer database.", from ? from : "main", fqn, to ? to : "main");
                        return;                                                                                                                        
                }                                                                                                                                      
                lua_remove( L2, -2);                                                                 // f                                              
                break;                
benoit-germain commented 10 years ago

Well, I've never used luasocket, but I guess that socket.core is a module, therefore it is likely to be a table. I'll have a look at all this when I summon the necessary time.

anfractuosity commented 10 years ago

Cheers I appreciate your help. Yeah that's a good point about it being a table.

What I'm really confused about though, is how this works when I run 'lua ipsum.lua' without "on_state_create = luaopen_mymodule", but it's necessary if I use lua embedded into my .c program.

benoit-germain commented 10 years ago

I've come up with a minimal test quite similar to your first attempt. The only difference is that I manually load the Lanes core DLL instead of compiling the Lanes sources files in the embedder application. I could have just as easily added core.lib at link time, but my work environment doesn't contain the location of core.dll in the search path

#include <windows.h>

extern "C"
{

#include "lanes.h"

}

static int load_lanes_lua( lua_State* L)
{
    if( 0 == luaL_dofile( L,"lanes.lua"))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
int main(int argc, char* argv[])
{
    typedef void (*luaopen_lanes_embedded_t)( lua_State* L, lua_CFunction _luaopen_lanes);

    HMODULE hCore = LoadLibrary( L"absolute_path_to\\core.dll");
    luaopen_lanes_embedded_t p_luaopen_lanes_embedded = (luaopen_lanes_embedded_t) GetProcAddress( hCore, "luaopen_lanes_embedded");

    lua_State* L = luaL_newstate();
    luaL_openlibs(L);

    p_luaopen_lanes_embedded( L, load_lanes_lua);
    lua_pop( L, 1);

    if( 0 == luaL_dostring(L,"local lanes = require 'lanes'.configure{with_timers = false}; return 'SUCCESS'"))
    {
        printf("%s\n",lua_tostring( L, -1));
    }

    lua_close(L);
}

I don't have any problem with that (my output is SUCCESS), provided that lanes.lua is in the working directory of the application. I suspect therefore that it wasn't the case for you (note that luaL_dofile won't use the search paths that are available to require)