2011-12-02 20 views
2

我想從Lua傳遞一個表到C,然後訪問C中的所有值,而無需將Lua地址空間中的值複製到C堆棧。有沒有辦法做到這一點?我想盡量減少值的副本。在C中從Lua傳遞的訪問表沒有複製值

我嘗試使用gettable(),但在這種情況下,該值被複制到棧頂。所以一個副本正在生成。我不想要這個。有沒有其他方法?

這是我的C代碼: -

#include <lua.h>        /* Always include this */ 
#include <lauxlib.h>       /* Always include this */ 
#include <lualib.h>       /* Always include this */ 
#include <malloc.h> 

#define EXCEPTION_IS_NUMBER (-2) //Passed a custom error no. to be returned in 
            //case of error 
#define SUCCESS (0) 

static int iquicksort(lua_State *L) { 
    int k,len=0; 
    len=lua_tointeger(L,-2);  //-2 specifies second element from top of stack. 
            //So I have passed 2 elements from Lua to C, first 
            //is size of table and second table. So when they 
            //are pushed to stack, the size is second element 
            //from top.So here I am storing it in variable len. 
    int *q; 
    int *p=(int *)malloc(len*sizeof(int)); 
    q=p; 
    for(k=1;k<=len;k++) 
    { 
      lua_pushinteger(L,k); //if I want to access a[2], where a is my table 
            //and 2 is the index, then '2' needs to be at top 
            //of the stack and I need to pass the location of 
            //'a' in stack as second argument to gettable(). 
            //So here Address of table was at top, I pushed 
            //the index on top, now address is second element 
            //from top. So I passed it as '-2' in gettable 
            //below. What gettable() does is that it fetches 
            //and copies that value at stack top. So I can 
            //use it from there. 
      lua_gettable(L,-2); 
      if(lua_isnumber(L,-1)) //Checking top value replaced by fxn is number... 
      { 
        *p++=lua_tointeger(L,-1); //Storing the values in array 
      } 
      else 
      { 
        lua_pushinteger(L,EXCEPTION_IS_NUMBER); 
        return 1; 
      } 
      lua_pop(L,1); 
    } 
    p=q; 
    sort(p,0,len-1); 
    for(k=1;k<=len;k++) //This fxn changes the value at prescribed location of table. 
          //here I am changing the values at Table's location... 
          //i.e. storing the sorted values in table..... 
    { 
      lua_pushinteger(L,k); 
      lua_pushinteger(L,*p++); 
      lua_settable(L,-3); 
    } 
    lua_pushinteger(L,SUCCESS); 
    return 1; 
} 

//Simple quicksort of values..... 
void sort(int *arr, int left,int right){ 
    int i = left, j = right; 
    int tmp; 
    int pivot = arr[(left + right)/2]; 

    /* partition */ 
    while (i <= j) { 
      while (arr[i] < pivot) 
        i++; 
      while (arr[j] > pivot) 
        j--; 
      if (i <= j) { 
        tmp = arr[i]; 
        arr[i] = arr[j]; 
        arr[j] = tmp; 
        i++; 
        j--; 
      } 
    }; 

    /* recursion */ 
    if (left < j) 
      sort(arr, left, j); 
    if (i < right) 
      sort(arr, i, right); 
} 

int luaopen_power(lua_State *L){ 
    lua_register(L,"quicksort",iquicksort); 
    return 0; 
} 

我通過使用下面的命令編譯該程序生成的共享庫: -

gcc -Wall -shared -fPIC -o power.so -I/usr/local/include/lua5.1 -llua5.1 quicksort.c 

下面是用於調用這個的Lua代碼: -

require("power") 
x={5,4,6,5,3,2,3,9} 
print("Before quicksort call....") 
t=quicksort(#x,x) 
if t==0 then 
     for i,v in ipairs(x) do print(i,v) end 
else 
     print(string.format("%s %d","Error occurred. Errorcode is:: ",t)) 
end 

感謝

+0

C和C++不是同一種語言。 –

回答

4

Lua的C API只複製低級C類型,如數字和布爾值。對於包括字符串在內的所有其他字符串,它使用指向內部Lua數據的指針。

+0

謝謝@lhf這樣一個很好的評論。你能幫我弄清楚字符串是如何通過的嗎?任何文件或工作的參考將不勝感激。我是新來的,我想了解它。再次感謝您的寶貴意見.... :) – Rahul

1

我不確定gettable()將值複製到Lua堆棧中,我認爲它複製了值的引用或指針...(特別是當該值本身是一個表時,該表的內容不會被複制) 。

而且鑑於Lua可能會做魔法處理,我相信你的回答是否定的。

的Lua是免費軟件可以download看源代碼。隨着lua-5.2.0-rc4lua_gettable功能是文件src/lapi.c

LUA_API void lua_gettable (lua_State *L, int idx) { 
    StkId t; 
    lua_lock(L); 
    t = index2addr(L, idx); 
    api_checkvalidindex(L, t); 
    luaV_gettable(L, t, L->top - 1, L->top - 1); 
    lua_unlock(L); 
} 

所以實際工作是由luaV_gettable從文件src/lvm.c這是

void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { 
    int loop; 
    for (loop = 0; loop < MAXTAGLOOP; loop++) { 
    const TValue *tm; 
    if (ttistable(t)) { /* `t' is a table? */ 
     Table *h = hvalue(t); 
     const TValue *res = luaH_get(h, key); /* do a primitive get */ 
     if (!ttisnil(res) || /* result is not nil? */ 
      (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ 
     setobj2s(L, val, res); 
     return; 
     } 
     /* else will try the tag method */ 
    } 
    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) 
     luaG_typeerror(L, t, "index"); 
    if (ttisfunction(tm)) { 
     callTM(L, tm, t, key, val, 1); 
     return; 
    } 
    t = tm; /* else repeat with 'tm' */ 
    } 
    luaG_runerror(L, "loop in gettable"); 
} 

所以我認爲答案是否定的完成。但是,您可以修補或增強代碼。我不明白爲什麼這個問題困擾你。只有簡單的數據纔會被複制(非常快),除非發生魔法(並且魔術,即metatable是Lua語義的一個重要部分);彙總數據內容不被複制。

+0

嗨巴西爾,我已經將代碼添加到我的問題。你可以看看它。 – Rahul

+0

我還添加了一些評論,讓您瞭解代碼的工作原理。 – Rahul

+0

它困擾我,因爲我必須分析TCP數據包,並希望我的代碼高效。數據包中的數據複製可能會導致問題,因爲我的內存數量有限,我必須減少副本。 – Rahul