在 C 中访问从 Lua 传递的表,而不复制值
我想将一个表从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
谢谢
I want to pass a table from Lua to C and then access all the values in C without copying the values from Lua address space to C stack. Is there a way of doing this?? I want to minimize the copy of values.
I tried using gettable() but in that case, the value is copied onto top of stack. So a copy is getting generated. I don't want this. Is there any other way??
Here is my C code:-
#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;
}
I generated a shared library by compiling this program using the following command:-
gcc -Wall -shared -fPIC -o power.so -I/usr/local/include/lua5.1 -llua5.1 quicksort.c
Here is the Lua code for calling this:-
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
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Lua 的 C API 仅复制低级 C 类型,例如数字和布尔值。对于所有其他内容,包括字符串,它使用指向内部 Lua 数据的指针。
The C API for Lua only copies low-level C types, such as numbers and booleans. For all others, including strings, it uses pointers to internal Lua data.
我不确定 gettable() 是否将值复制到 Lua 堆栈,我认为它复制了该值的引用或指针...(特别是当该值本身是一个表时,该表的内容不被复制)。
鉴于Lua可能会进行魔法处理,我相信你的答案是否定的。
Lua 是免费软件,您可以下载它并查看源代码。对于
lua-5.2.0-rc4
,lua_gettable
函数位于文件src/lapi.c
中,因此实际工作由
完成luaV_gettable
来自文件src/lvm.c
,所以我认为答案是否定的。但是,您可以修补或增强代码。我不明白为什么这个问题让你烦恼。仅复制简单数据(非常快),除非发生魔法(而魔法即元表是 Lua 语义的重要组成部分);聚合数据内容不会被复制。
I'm not sure that
gettable()
copies the value to the Lua stack, I think it copies a reference or pointer of the value... (especially when that value is a table itself, that table 's content is not copied).And given that Lua may do magic processing, I believe your answer is no.
Lua being free software you can download it and look in the source code. With
lua-5.2.0-rc4
thelua_gettable
function is in filesrc/lapi.c
so the actual work is done by
luaV_gettable
from filesrc/lvm.c
which isso I think the answer is no. However, you could patch or enhance the code. I don't understand why the question bothers you. Only simple data is copied (very quickly), unless magic occurs (and the magic i.e. metatable is an essential part of Lua semantics); aggregate data content is not copied.