Luaplus C ++ function Interaction

Source: Internet
Author: User

<--! All rights reserved foruok. Reprinted with the source! -->

Call C ++ functions and objects from Lua
With luaplus, you can easily call the Lua script from C ++. By registering a function or class object, Lua can access C ++.

I. C-style function Registration
Lua provides C-style callback function registration. The function prototype is as follows:
Int callback (luastate * State );

You can register with Lua as long as global functions, non-virtual functions, and virtual functions comply with the preceding prototype. Taking global functions as an example, the following is a callback function cstyleaddfunc:

Int cstyleaddfunc (luastate * State)
{Luastack ARGs (State );
If (ARGs [1]. isnumber () & ARGs [2]. isnumber ())
{State-> pushnumber (ARGs [1]. getinteger () + ARGs [2]. getinteger ());
Return 1;
}
Return 0;
}

In the callback function, we use the stack to access parameters. The stack can store multiple parameters, luastack ARGs (State); the statement gets the stack object for subsequent access. Next, determine whether the parameter is a number. If both parameters are numbers, add the result to the stack and return the number of data pushed to the stack. Note that the return value indicates the number of elements pushed into the stack, rather than the return value of some computing result or other meaning. View by changing the return valueProgramIn this way, you can have a perceptual knowledge of the meaning of the returned value. To register and return, you only need to call the register function, which is used in the first article. The following is a test function:

Void testcfunctioncallback ()
{
Luastateowner state; // "print" need this
State-> openlibs (); // register my function cstyleaddfunc to add
State-> getglobals (). Register ("add", cstyleaddfunc); // call my function and print the result
State-> dostring ("ret = add (1, 5); print (RET )");
}

State-> dostring ("ret = add (); print (RET)"); this sentence is used to execute the Lua command string. Call add and assign the result to the RET variable, and then print the RET value. The main function is as follows:

Int _ tmain (INT argc, _ tchar * argv [])
{
Testcfunctioncallback ();
Return 0;
}

Compile and run, everything is OK. We can also call the registered callback function from the Lua script file, as shown in the first article. To register a member function of the class, you need to call another form of register (const char * funcname, const callee & callee, INT (callee: * func) (luastate *), int nupvalues = 0);, provides class instance pointers and functions to complete registration. The following is an exampleCode:

class ctestcallback
{< br> Public:
int nonvirtualfunc (luastate * State)
{< br> luastack ARGs (State );
printf ("in non-virtual member function. no MSG. ");
return 0;
}< br>
int virtual virtualfunc (luastate * State)
{< br> luastack ARGs (State );
printf ("in virtual member function. MSG = % s ", argS [1]. getstring ();
return 0;
}< BR >};

Void testclassmemberfuncreg ()
{
Luastateowner state; // "print" need this
State-> openlibs ();
Luaobject globalobj = state-> getglobals ();
Ctestcallback TCB;
Globalobj. Register ("memberfunc", TCB, & ctestcallback: nonvirtualfunc );
State-> dostring ("memberfunc ()");
Globalobj. Register ("virmemberfunc", TCB, & ctestcallback: virtualfunc );
State-> dostring ("virmemberfunc ('Hi, myboys ')");
}

Modify the main function and add testclassmemberfuncreg () to view the effect.

 

II. C ++ function registration in any form
Luaplus provides registerdirect () to directly register functions of any form, which is more direct and convenient to use without being limited by the previous function prototype. Similarly, this function can be used to register a class member function like register (you also need to display the specified this pointer ). The following code is used:

Float add (float num1, float num2)
{
Return num1 + num2;
}

Class cforregdirect
{
Public:
Int sum (int A, int B, int C)
{
Return A + B + C;
} // Const is necessary
Virtual void seemessage (const char * MSG)
{
Printf ("MSG = % s", MSG );
}
};

void testregisterdirect ()
{< br> luastateowner state;
state-> openlibs ();
luaobject gobj = state-> getglobals (); // register global function directly
gobj. registerdirect ("add", add);
state-> dostring ("Print (add (1.5, 2.3)"); // register memberfunction
cforregdirect forobj;
gobj. registerdirect ("membersum", forobj, cforregdirect: Sum);
state-> dostring ("Print (membersum (1, 2, 7)) ");
gobj. registerdirect ("vircmsg", forobj, cforregdirect: seemessage);
state-> dostring ("Print (vircmsg ('haha, do you see me? ') ");
}

3. Register a correspondence object
The preceding two sections can implement simple callback registration. When registering a member function of a Class, Class pointers must be explicitly provided, which is not suitable for ing class structures in C ++. Registerobjectfunctor () and metadata table (writable) provide a new method. We do not need to explicitly provide the this pointer when registering a function as an alternative. This pointer can be obtained from the caller's userdata or _ OBJECT member. A metadata table is a common table object that defines some operations that can be rewritten, such as ADD, sub, Mul, index, and call, these operations start with "_", such as _ add ,__ index. If you overwrite _ add, the _ add operation you have defined will be called during the add operation. This feature can be used to simulate class objects in C ++. Registering a function object uses this feature. Next we will map a C ++ class to Lua. The class code is as follows:

Class cmultiobject
{
Public:
Cmultiobject (INT num): m_num (Num)
{}

Int print (luastate * State)
{
Printf ("% d", m_num );
Return 0;
}
Protected:
Int m_num;

};
Void testregobjectdispatchfunctor ()
{
Luastateowner state;
State-> openlibs (); // create writable able
Luaobject uploableobj = state-> getglobals (). createtable ("multiobjectconfigurable ");
Metatableobj. setobject ("_ Index", metatableobj); // register functor for multiobject
Metatableobj. registerobjectfunctor ("print", cmultiobject: print); // get a instances of cmultiobject
Cmultiobject obj1 (10); // "clone" A object in Lua, The Lua object (here is table) has obj1's data
Luaobject obj1obj = state-> boxpointer (& obj1); // set Lua object's writable able to writable ableobj
Obj1obj. setmetatable (metatableobj); // put Lua object to global scope, thus it can be accessed later.
State-> getglobals (). setobject ("obj1", obj1obj );
Cmultiobject obj2 (20 );
Luaobject obj2obj = state-> boxpointer (& obj2 );
Obj2obj. setmetatable (metatableobj );
State-> getglobals (). setobject ("obj2", obj2obj); // now call print and print2
State-> dostring ("obj1: Print ();");
State-> dostring ("obj2: Print ();");
}

First, we need to generate a metadata table and register the member functions of the C ++ class to the metadata table. Then, generate the corresponding object (also a table) in Lua Based on the cmultiobject instance, and divide the object's retriable (that is, the _ OBJECT Member of the table) set it to the generated meta table. Finally, place the newly generated Lua objects in the global scope so that these objects can be directly referenced later. We can make an approximate understanding that the data elements of each instance are stored in the corresponding Lua table, while the member functions of the class are stored in the writable able (correspondence object ). When obj1obj: Print () is called, it will first find its retriable, and then find the print () function in the retriable. In this way, the class structure like C ++ is implemented. Each instance has its own data, and all instances share a list of methods. Another method is to use the userdata of the table. You must first create a Lua table object, then, set the C ++ object obj1 to the userdata (also set its _ OBJECT member) of the table, and set the retriable of the table object to the meta table we created earlier. Finally, we can call the print function with a representation. The Code is as follows:

Luaobject table1obj = state-> getglobals (). createtable ("Table1 ");
Table1obj. setlightuserdata ("_ object", & obj1 );
Table1obj. setmetatable (metatableobj );
Luaobject table2obj = state-> getglobals (). createtable ("Table2 ");
Table2obj. setlightuserdata ("_ object", & obj2 );
Table2obj. setmetatable (metatableobj );
State-> dostring ("Table1: Print ()");
State-> dostring ("Table2: Print ()");

Registerobjectfunctor: the function to be registered must comply with the prototype (INT callback (luastate * State );). To break this restriction, luaplus provides another method.



4. register the correspondence object directly

Directly registering a function subobject (registerobjectdirect) is similar to registerdirect. If you do not consider the function prototype, you can directly register any form of function with the meta table. Add a new member function to cmultiobject:

Void print2 (INT num)
{
Printf ("% d \ n", m_num, num );
}

Call the registerobjectdirect method:
Metatableobj. registerobjectdirect ("print2", (cmultiobject *) 0, & cmultiobject: print2 );

The second parameter (cmultiobject *) 0 is a bit strange, which is required by the template parameters.

Finally:
State-> dostring ("obj1: print2 (5 )");
State-> dostring ("obj2: print2 (15 )");
State-> dostring ("Table1: print2 (5 )");
State-> dostring ("Table2: print2 (15 )");

5. logout callback

Canceling callback is a simple task. Call setnil ("yourcallback"), for example:
Gobj. setnil ("add ");
Metatableobj. setnil ("print2 ");

Well, the longest article so far looks like a luaplus document translation (?), However, I have added some of my own understandings. I read the document and thought about it for half a day. We hope to use luaplus quickly.
MATERIALS: (1) lua5.1 Reference Manual (2) Lua entry wiki (3366luaplus.html, included in the source code package.
<--! All rights reserved foruok. Reprinted with the source! -->

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.