从c api中创建lua表时出错

时间:2014-08-21 14:28:31

标签: c lua lua-table lua-api

我在C中有一个A *算法,打算从Lua中使用。现在,A *本身工作正常但是出于一些奇怪的原因,当我从Lua调用它时,当任何一个参数函数(邻居)创建一个表时,会弹出一个奇怪的错误。在C中创建表工作正常。 这个库有两个版本 - 第一个版本直接从C中的主要版本中调用脚本'功能,并从Lua创建表格顺利。第二个编译为dll并由脚本加载,在创建表时崩溃。为什么,我不知道。 我已经尝试在C中分配所有内存并传递lightuserdata,但它没有任何区别。 我在同一台机器上编译了其他.dll,并没有复制此错误。

C LIBRARY

int run(lua_State *L)
                      /*
                      1: string from, 
                      2: string to, 
                      3: string[] Neighbours(string of),
                      4: int Cost(string from, string to, string dest),
                      5: int Heuristic(string from, string to, string dest)
                      */
{
    char flag = 0;
    HE = HE ? HE : Heap_Alloc(200);
    Heap_Clear(HE);

    // create the HASHtable
    lua_createtable(L,1,300);
    // 6 - HASHtable (string -> {int cost,string Self,string parent})


    // get Heuristic(0,from,to)
    lua_pushvalue(L,5);
    lua_pushstring(L,0);
    lua_pushvalue(L,1);
    lua_pushvalue(L,2);
    lua_call(L,3,1); 

    {
        // 7 - Heuristic(0,from,to)
        Heap_val_t hp = {lua_tointeger(L,7), lua_tostring(L,1)};
        Z q;

        // HASH[from] = {cost=Heuristic, self=from, parent=nil}
        lua_pushvalue(L,1);
        lua_newuserdata(L,sizeof(struct g));
        q = lua_touserdata(L,-1);
        q->_cost = lua_tointeger(L,7);
        q->_self = lua_tostring(L,1);
        q->_parent = 0;
        lua_rawset(L,6);

        // pop Heuristic(0,from,to) (6)
        lua_pop(L,1);

        Heap_Push_macro(HE, hp);


        while (!Heap_Empty(HE))
        {
            int i=1;
            hp = Heap_Top(HE);
            Heap_Pop_macro(HE);

            // push Neighbours(Self) on the stack
            lua_pushvalue(L,3);
            lua_pushstring(L,hp._self);
            lua_call(L,1,1); // ALLOCATING TABLE INSIDE THIS GENERATES THE ERROR


            while(1)
            {
                // 7 - neighbours table[]

                // push neighbours[i]
                lua_rawgeti(L,-1,i);

                // check if we got to the end of neighbours
                if (!lua_isstring(L,-1))
                {
                    lua_pop(L,1);
                    break;
                }
                {
                    // 8 - neighbours[i]
                    int cost,heur;

                    // get HASH[hp.self].cost and pop from stack
                    lua_pushstring(L,hp._self);
                    lua_rawget(L,6);
                    q = lua_touserdata(L,-1);
                    cost = q->_cost;
                    lua_pop(L,1);

                    // call Cost(hp.self,*neighbours,to)
                    lua_pushvalue(L,4);
                    lua_pushstring(L,hp._self);
                    lua_pushvalue(L,8);
                    lua_pushvalue(L,2);
                    lua_call(L,3,1);
                    // add it to cost and remove from stack
                    cost += lua_tointeger(L,-1);
                    lua_pop(L,1);

                    // get Heuristic(hp._obj, *neighbours, to) and pop it
                    lua_pushvalue(L,5);
                    lua_pushstring(L,hp._self);
                    lua_pushvalue(L,8);
                    lua_pushvalue(L,2);
                    lua_call(L,3,1);
                    heur = lua_tointeger(L,-1);
                    lua_pop(L,1);

                    // get HASH[*neighbours]
                    lua_pushvalue(L,8);
                    lua_rawget(L,6);
                    q = lua_touserdata(L,-1);

                    if (!q  ||  q->_cost > cost+heur)
                    {
                        Heap_val_t  y = {cost+heur, lua_tostring(L,8)};
                        Heap_Push_macro(HE, y);
                        // HASH[*neighbours] = {cost=cost, self=*neighbours, parent=hp.self}
                        lua_pushvalue(L,8);
                        lua_newuserdata(L,sizeof(struct g));
                        q = lua_touserdata(L,-1);
                        q->_cost = cost;
                        q->_self = lua_tostring(L,8);
                        q->_parent = hp._self;
                        lua_rawset(L,6);
                    }
                    // remove 10
                    lua_pop(L,1);               
                    // 9

                }
                // remove neighbours[i]
                lua_pop(L,1);
                i++;
                // 8
            }


            // remove neighbours[]
            lua_pop(L,1);
            // 7

            lua_pushstring(L,hp._self);
            if (lua_equal(L,-1,2))
            {
                flag = 1;
                // pop the string
                lua_pop(L,1);
                break;
            }
            lua_pop(L,1);   
        }


        // 7 - return path table
        lua_createtable(L,1,1);
        if (flag)
        {
            int i=1,j;

            while(1)
            {
                Z g;
                lua_pushvalue(L,2);
                lua_rawget(L,6);
                g = lua_touserdata(L,-1);
                if (!g->_parent)
                {
                    lua_pop(L,1);
                    break;
                }

                lua_pushstring(L,g->_parent);
                lua_replace(L,2);
                lua_pushstring(L,g->_self);
                lua_rawseti(L,7,i++);
                lua_pop(L,1);
            }

            // reverse the table
            for (j=1, i--;  i-j > 0;  i--,j++)
            {
                lua_rawgeti(L,7,j);
                lua_rawgeti(L,7,i);
                lua_rawseti(L,7,j);
                lua_rawseti(L,7,i);
            }
        }
    }

    // replace HASH with return table
    lua_replace(L,6);
    return 1;
}

LUA SCRIPT

require 'astar'

function X(z)
    local a = z:find'[? ]'
    return tonumber(z:sub(1,a))
end
function Y(z)
    local a = z:find'[? ]'
    return tonumber(z:sub(a))
end


m,n = {-1,-1,-1,0,0,1,1,1},{-1,0,1,-1,1,-1,0,1}
function neighbours(of)
    print('neighbours',of)
    local x,y = X(of),Y(of)
    -- local r = {} -- creating a table from inside the C api crashes
    local r = 0

    for i=1,#m do
        local nx,ny = x+m[i],y+n[i]
        --table.insert(r,nx..' '..ny)
    end

    return r
end

function cost(from,to,dest)
    return 1
end
function heuristic(from,to,dest)
    local x1,y1,x2,y2 = X(to),Y(to),X(dest),Y(dest)
    return math.abs(x1-x2)+math.abs(y1-y2)
end


print{}     -- making tables before C api call..
r = astar.run('0 0','1 0', neighbours, cost, heuristic)
print{}     -- ..or after doesn't crash

print('r',r)
if r then
    print(#r)
    for i,j in pairs(r) do
        print(i,j)
    end
end

1 个答案:

答案 0 :(得分:0)

我终于明白了:Lua不喜欢pendrives。 当我卸载vc ++项目并从我的硬盘驱动器构建它时,一切都正常。 孩子们,不要在pendrive上建立Lua库。