Таблица доступа передана из Lua в C без копирования значений - PullRequest
2 голосов
/ 02 декабря 2011

Я хочу передать таблицу из Lua в C, а затем получить доступ ко всем значениям в C, не копируя значения из адресного пространства Lua в стек C.Есть ли способ сделать это ??Я хочу минимизировать копию значений.

Я пытался использовать 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

Спасибо

Ответы [ 2 ]

4 голосов
/ 02 декабря 2011

C API для Lua копирует только низкоуровневые типы C, такие как числа и логические значения.Для всех остальных, включая строки, он использует указатели на внутренние данные Lua.

1 голос
/ 02 декабря 2011

Я не уверен, что gettable() копирует значение в стек Lua, я думаю, что он копирует ссылку или указатель значения ... (особенно, если это значение является самой таблицей, содержимое этой таблицыне копируется).

И учитывая, что Луа может выполнять магическую обработку, я считаю, что ваш ответ - нет.

Луа - свободное программное обеспечение вы можете скачать это и посмотрите в исходном коде lua-5.2.0-rc4 функция lua_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");
}

так что я думаю, что ответ - нет.Тем не менее, вы можете исправить или улучшить код.Я не понимаю, почему этот вопрос вас беспокоит.Копируются только простые данные (очень быстро), если не происходит волшебства (а магия, т.е. метатабельная, является неотъемлемой частью семантики Lua);агрегированное содержимое данных не копируется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...