在C ++和Lua之间来回发送变量指针? [英] Sending variable pointers back and forth between C++ and Lua?

查看:383
本文介绍了在C ++和Lua之间来回发送变量指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方法来在C ++和Lua之间来回传递变量地址。例如,将对象从C ++传输到Lua并进行一些处理,然后将其传输回C ++。



然而,事情是如何从Lua执行C ++函数或方法?



如果可能,您能否包含代码段来告诉我它是如何完成的?


解决方案

我知道我还不完全了解整个图片,所以如果有什么不对,请纠正我。 p>我花了很多时间来使Lua与C ++类一起工作。 Lua比C ++更多的是C风格的API,但是有很多方法可以使用C ++。



在Lua C API中,一个指针由userdata或 light userdata ,它们没有元表,并且不会被垃圾回收)。 Userdata可以与一个metatable相关联,它将像Lua中的类一样起作用。



考虑一个带有私有成员的基本person类name(ac string)和age(int)。名称由构造函数设置,不能更改。年龄与吸气剂和安定剂接触:

 类人
{
私人:
const char * name;
int age;
public:
person(const char * n){
name = strdup(n)
}
〜person(){
free((void *)name);
}
void print(){
printf(%s is%i \\\
,name,age);
}
int getAge(){
return this-> age;
}
void setAge(int a){
this-> age = a;
}
};

为了向Lua揭示这个问题,我将为所有符合lua_CFunction的方法原型,它将lua状态作为参数,并返回一个int值,它推送到堆栈的值(通常为一个或零)。



函数是构造函数,它将返回一个类似对象的Lua表。为此,lua_newuserdata用于创建指向对象的指针。我将假设我们将在Lua init期间创建一个包含这些c函数的元表Person。这个元表必须与构造函数中的userdata相关联。

  //包装构造函数
int L_newPerson(lua_State * L){
//指向指针的指针
person ** p =(person **)lua_newuserdata(L,sizeof(person *));
//指向人的指针
* p =新人(lua_tostring(L,1));
//与Person元表相关联
lua_getglobal(L,Person);
lua_setmetatable(L,-2);
return 1;
}

当创建其他方法时,只需要记住第一个参数将始终是我们使用newPerson创建的指针。要获得C ++对象,我们只是取消引用lua_touserdata(L,1);的返回值。

  int L_print lua_State * L){
person ** p =(person **)lua_touserdata(L,1)
(* p) - > print();
return 0;
}

int L_getAge(lua_State * L){
person ** p =(person **)lua_touserdata(L,1)
lua_pushnumber(L,(* p) - > getAge());
return 1;
}

int L_setAge(lua_State * L){
person ** p =(person **)lua_touserdata(L,1)
(* p) - > setAge(lua_tonumber(L,2));
return 0;
}



最后,在初始化Lua期间,使用luaL_register设置Person元表。

  //我们的方法... 
static const luaL_Reg p_methods [] = {
{new ,L_newPerson},{print,L_print},
{getAge,L_getAge},{setAge,L_setAge},
{NULL,NULL}
}

lua_State * initLuaWithPerson(){
lua_State * L = lua_open();
luaL_openlibs(L);
luaL_register(L,Person,p_methods);
lua_pushvalue(L,-1);
lua_setfield(L,-2,__index);
return L;
}

并测试...

  const char * Lua_script = 
p1 = Person.new('Angie'); p1:setAge(25)
p2 = Person.new('Steve'); p2:setAge(32);
p1:print(); p2:print();

int main(){
lua_State * L = initLuaWithPerson();
luaL_loadstring(L,Lua_script);
lua_pcall(L,0,0,0);
return 0;
}

还有其他方法在Lua中实现OO。本文包含替代方案:
http://loadcode.blogspot.com /2007/02/wrapping-c-classes-in-lua.html


I am looking for a way to transfer the variable addresses back and forth between C++ and Lua. For instance, transferring an object from C++ to Lua and do some processing, then transfer it back to C++.

However, the thing is how can you execute a C++ functions or methods from Lua? Or is a workaround required?

If possible, could you include a code snippet to show me how it is done?

I am aware that I do not fully understand the whole picture yet, so if something is amiss, please correct me.

解决方案

It took me a lot of fiddling around to get Lua to work well with C++ classes. Lua is much more of a C style API than C++ but there are plenty of ways to use it with C++.

In the Lua C API a pointer is represented by userdata (or light userdata which have no metatables and are not garbage collected). Userdata can be associated with a metatable which will act a bit like a class in Lua. The C functions that are a part of that metatable wrap the c++ class's methods and act as the class's methods in Lua.

Consider a basic person class with private members name (a c string) and age (an int). Name is set by the constructor and can not change. Age is exposed with a getter and setter:

class person
{
  private:  
    const char* name;
    int age;
  public:
    person(const char* n) {
        name = strdup(n);
    }
    ~person() {
        free((void*)name);
    }
    void print() {
        printf("%s is %i\n",name, age);
    }
    int getAge() {
        return this->age;
    }
    void setAge(int a) {
        this->age=a;
    }
};

To expose this to Lua first I will write wrapper functions for all of the methods that conform to the lua_CFunction prototype which takes the lua state as an argument and returns an int for the number of values it pushed on to the stack (usually one or zero).

The trickiest of these functions is the constructor which will return a Lua table which acts like an object. To do this lua_newuserdata is used to create a pointer to the pointer to the object. I will assume that we are going to create a meta table "Person" during the Lua init which contain these c functions. This meta table must be associated with the userdata in the constructor.

// wrap the constructor
int L_newPerson(lua_State* L) {
    //pointer to pointer
    person **p = (person **)lua_newuserdata(L, sizeof(person *));
    //pointer to person
    *p = new person(lua_tostring(L, 1)); 
    // associate with Person meta table
    lua_getglobal(L, "Person"); 
    lua_setmetatable(L, -2); 
    return 1;
}

When the other methods are created, you just have to remember that the first argument will always be the pointer to the pointer we created with newPerson. To get the C++ object from that we just de-reference the return from lua_touserdata(L, 1);.

int L_print(lua_State* L) {
    person** p = (person**) lua_touserdata(L, 1);
    (*p)->print();
    return 0;
}

int L_getAge(lua_State* L) {
    person** p = (person**) lua_touserdata(L, 1);
    lua_pushnumber(L, (*p)->getAge());
    return 1;
}

int L_setAge(lua_State* L) {
    person** p = (person**) lua_touserdata(L, 1);
    (*p)->setAge(lua_tonumber(L, 2));
    return 0;
}

Finally the Person meta table is set up using luaL_register during the initializing of Lua.

// our methods...
static const luaL_Reg p_methods[] = {
    {"new", L_newPerson},{"print", L_print},
    {"getAge", L_getAge},{"setAge", L_setAge}, 
    {NULL, NULL}
};

lua_State* initLuaWithPerson() {
    lua_State* L=lua_open();
    luaL_openlibs(L);
    luaL_register(L, "Person", p_methods);  
    lua_pushvalue(L,-1);
    lua_setfield(L, -2, "__index"); 
    return L;
}

and to test it...

const char* Lua_script = 
    "p1=Person.new('Angie'); p1:setAge(25);"
    "p2=Person.new('Steve'); p2:setAge(32);"
    "p1:print(); p2:print();";

int main() {
    lua_State* L=initLuaWithPerson();
    luaL_loadstring(L, Lua_script);
    lua_pcall(L, 0, 0, 0);
    return 0;
}

There are other ways to implement OO in Lua. This article covers alternatives: http://loadcode.blogspot.com/2007/02/wrapping-c-classes-in-lua.html

这篇关于在C ++和Lua之间来回发送变量指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆