Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用c编写oo Lua接口的最佳方法?_C_Object_Lua - Fatal编程技术网

用c编写oo Lua接口的最佳方法?

用c编写oo Lua接口的最佳方法?,c,object,lua,C,Object,Lua,考虑以下示例(一个简单的2d向量库)。这里有一个构造函数,它返回一个包含方法的对象表。我对这种方法的问题是,它使用每个构造函数创建新表。是否有一种方法可以使用表的单个实例,但只更改_数据字段,该字段用于标识方法处理的点?这是更好的方法吗 #include <stdlib.h> #include <assert.h> #include <stdio.h> #include "lua.h" #include "lauxlib.h" #include "lualib

考虑以下示例(一个简单的2d向量库)。这里有一个构造函数,它返回一个包含方法的对象表。我对这种方法的问题是,它使用每个构造函数创建新表。是否有一种方法可以使用表的单个实例,但只更改_数据字段,该字段用于标识方法处理的点?这是更好的方法吗

#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

const char* test = 
"p1 = point(410, 680);"
"p2 = point(320, 120);"
"print('dot='..p1:dot(p2));"
"print('cross='..p1:cross(p2));";

typedef struct point_t {
    lua_Number x, y;
} point_t;

point_t* p_new(lua_Number x, lua_Number y) {
    point_t* p = malloc(sizeof(point_t));
    p->x = x;
    p->y = y;
    return p;
}

void lua_settabledata(lua_State *L , char * key , void * value) {
    lua_pushstring(L, key);
    lua_pushlightuserdata(L, value);
    lua_settable(L, -3);
}

void lua_settablefunction(lua_State *L, char * key , lua_CFunction value) {
    lua_pushstring(L, key);
    lua_pushcfunction(L, value);
    lua_settable(L, -3);
}

point_t* lua_topoint(lua_State *L, int index) {
    point_t* p;
    lua_pushstring(L, "_data");
    lua_gettable(L, index);
    p = lua_touserdata(L, -1);
    lua_pop(L, 1);
    assert(p);
    return p;
}

int l_dot(lua_State *L) {
    point_t* p1 = lua_topoint(L, 1);
    point_t* p2 = lua_topoint(L, 2);
    lua_pushnumber(L, p1->x*p2->x + p1->y*p2->y);
    return 1;
}

int l_cross(lua_State *L) {
    point_t* p1 = lua_topoint(L, 1);
    point_t* p2 = lua_topoint(L, 2);
    lua_pushnumber(L, p1->x*p2->y - p1->y*p2->x);
    return 1;
}

int l_setx(lua_State *L) {
    point_t* p = lua_topoint(L, 1);
    p->x = lua_tonumber(L, 2);
    return 0;
}

int l_sety(lua_State *L) {
    point_t* p = lua_topoint(L, 1);
    p->y = lua_tonumber(L, 2);
    return 0;
}

int l_getx(lua_State *L) {
    point_t* p = lua_topoint(L, 1);
    lua_pushnumber(L, p->x);
    return 1;
}

int l_gety(lua_State *L) {
    point_t* p = lua_topoint(L, 1);
    lua_pushnumber(L, p->y);
    return 1;
}

int l_point(lua_State* L) {
    lua_Number x = lua_tonumber(L, 1);
    lua_Number y = lua_tonumber(L, 2);
    lua_newtable(L);
    lua_settabledata(L , "_data", p_new(x, y));
    lua_settablefunction(L , "dot", l_dot);
    lua_settablefunction(L , "cross", l_cross);
    lua_settablefunction(L , "setx", l_setx);
    lua_settablefunction(L , "sety", l_sety);
    lua_settablefunction(L , "getx", l_getx);
    lua_settablefunction(L , "gety", l_gety);
    return 1;
}

int main() {
    lua_State* L = lua_open();
    luaL_openlibs(L);
    lua_register(L, "point", l_point);
    if (luaL_loadstring(L, test) || lua_pcall(L, 0, 0, 0))
       printf("error: %s", lua_tostring(L, -1));
    getchar();
    return 0;
}
#包括
#包括
#包括
#包括“lua.h”
#包括“lauxlib.h”
#包括“lualib.h”
常量字符*测试=
p1=点(410680)
p2=点(320,120)
“打印('dot='…p1:dot(p2));”
“打印('cross='…p1:cross(p2));”;
类型定义结构点{
lua_数x,y;
}重点;;
点t*p_新(lua_编号x,lua_编号y){
point_t*p=malloc(sizeof(point_t));
p->x=x;
p->y=y;
返回p;
}
void lua_settabledata(lua_State*L,char*键,void*值){
lua_推力串(L,键);
lua_pushlightuserdata(L,值);
lua_可设置(L,-3);
}
void lua_settablefunction(lua_State*L、char*键、lua_CFunction值){
lua_推力串(L,键);
lua_pushc函数(L,值);
lua_可设置(L,-3);
}
点t*lua\u拓扑点(lua\u状态*L,整数索引){
点t*p;
lua_推力串(L,“_数据”);
lua_可获取(L,索引);
p=lua_-Tuserdata(L,-1);
卢厄波普(L,1);
断言(p);
返回p;
}
内部l_点(lua_状态*l){
点t*p1=lua\u点(L,1);
点t*p2=lua\u点(L,2);
lua_pushnumber(L,p1->x*p2->x+p1->y*p2->y);
返回1;
}
内部l_交叉(lua_州*l){
点t*p1=lua\u点(L,1);
点t*p2=lua\u点(L,2);
lua_pushnumber(L,p1->x*p2->y-p1->y*p2->x);
返回1;
}
int l_setx(lua_州*l){
点t*p=lua\u点(L,1);
p->x=lua_tonumber(L,2);
返回0;
}
内卢州(卢奥州*l){
点t*p=lua\u点(L,1);
p->y=lua_tonumber(L,2);
返回0;
}
int l_getx(lua_州*l){
点t*p=lua\u点(L,1);
lua_pushnumber(L,p->x);
返回1;
}
国际法(卢厄州*l){
点t*p=lua\u点(L,1);
lua_pushnumber(L,p->y);
返回1;
}
内部l_点(lua_状态*l){
lua_数x=lua_数(L,1);
lua_数y=lua_数(L,2);
新表(L);
lua_settabledata(L,“_data”,p_new(x,y));
lua_可设置函数(L,“点”,L_点);
lua_可设置函数(L,“交叉”,L_交叉);
lua_settablefunction(L,“setx”,L_setx);
lua_settablefunction(L,“sety”,L_sety);
lua_settablefunction(L,“getx”,L_getx);
lua_settablefunction(L,“gety”,L_gety);
返回1;
}
int main(){
lua_State*L=lua_open();
luaL_openlibs(L);
lua_寄存器(L,“点”,L_点);
if(luaL_loadstring(L,test)| lua_pcall(L,0,0,0))
printf(“错误:%s”,lua_tostring(L,-1));
getchar();
返回0;
}

考虑使用它,它允许您的lua代码直接与c/c++代码的指定部分交互。

考虑使用它,它允许您的lua代码直接与c/c++代码的指定部分交互。

我刚刚浏览了您的代码,但看起来每个对象都是一个表,其中包含一个带有实例数据的轻型userdatum,以及一组封装在Lua闭包中的C函数。是的,这是非常低效的。第一个改进是不要对每个实例使用相同的C函数进行单独的闭包。但我们甚至可以做得更好

你不能做你想象的事情:你不能在对象之间共享一个表,但是每个对象有一个不同的字段。如果一个字段不同,那么您就得到了一个不同的表

但您可以以更高效的方式划分共享数据和实例数据

不需要创建表来保存实例数据。只需将分配的结构设置为(完整的,而不是轻量级的)用户数据。这比桌子小一点。(我认为x86_64;上的40字节比64字节加上分配结构的大小。)

您将把所有方法放在一个方法表中,并将该表与您返回的所有用户数据相关联。共享数据可以多种方式与对象关联。由于您希望在Lua中可以访问这些方法,因此需要将方法表分配给
M.\uu index
,其中
M
是每个实例对象的元表。所有对象都可以指定一个共享的M,如果您愿意,M可以包含方法本身(那么
M.\uu index
将仅为M)

在元表中,您还需要放置一个
\uu gc
方法,以便在垃圾收集对象时释放分配的结构


看一看。另外,我们还将在上查看lv3软件包。(他是Lua的作者之一。)

我刚刚浏览了您的代码,但看起来您的每个对象都是一个表,其中包含一个带有实例数据的轻用户数据,以及包装在Lua闭包中的一组C函数。是的,这是非常低效的。第一个改进是不要对每个实例使用相同的C函数进行单独的闭包。但我们甚至可以做得更好

你不能做你想象的事情:你不能在对象之间共享一个表,但是每个对象有一个不同的字段。如果一个字段不同,那么您就得到了一个不同的表

但您可以以更高效的方式划分共享数据和实例数据

不需要创建表来保存实例数据。只需将分配的结构设置为(完整的,而不是轻量级的)用户数据。这比桌子小一点。(我认为x86_64;上的40字节比64字节加上分配结构的大小。)

您将把所有方法放在一个方法表中,并将该表与您返回的所有用户数据相关联。共享数据可以通过多种方式与对象关联