1、Lua和C++交互
1、lua和c++交互機(jī)制是基于一個(gè)虛擬棧,C++和lua之間的所有數(shù)據(jù)交互都通過(guò)這個(gè)虛擬棧來(lái)完成,無(wú)論何時(shí)C++想從lua中調(diào)用一個(gè)值,被請(qǐng)求的值將會(huì)被壓入棧,C++想要傳遞一個(gè)值給Lua,首選將整個(gè)值壓棧,然后就可以在Lua中調(diào)用。
2、lua中提供正向和反向索引,區(qū)別在于證書(shū)永遠(yuǎn)是棧底,負(fù)數(shù)永遠(yuǎn)是棧頂。
2、基礎(chǔ)練習(xí)
編譯指令:g++ test.cpp -o test -llua -ldl
#include <iostream>
#include <string.h>
using namespace std;
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
// g++ test.cpp -o test -llua -ldl
int main()
{
//1.創(chuàng)建一個(gè)state
// luaL_newstate返回一個(gè)指向堆棧的指針
lua_State *L = luaL_newstate();
//2.入棧操作
lua_pushstring(L, "hello world");
lua_pushnumber(L, 200);
//3.取值操作
if (lua_isstring(L, 1)) { //判斷是否可以轉(zhuǎn)為string
cout << lua_tostring(L, 1) << endl; //轉(zhuǎn)為string并返回
}
if (lua_isnumber(L, 2)) {
cout << lua_tonumber(L, 2) << endl;
}
//4.關(guān)閉state
lua_close(L);
return 0;
}
2.1、加載Lua腳本并傳遞參數(shù)
編譯指令:g++ test.cpp -o test -llua -ldl
函數(shù)說(shuō)明:
1、函數(shù)用于將Lua腳本加載到Lua虛擬機(jī)中并進(jìn)行編譯
luaL_loadbuffer(L,s,sz,n)
lua_State *L:Lua狀態(tài)對(duì)象,表示Lua虛擬機(jī)的運(yùn)行實(shí)例。
const char *buff:指向Lua腳本內(nèi)容的字符串。
size_t sz:Lua腳本內(nèi)容的長(zhǎng)度。
const char *name:可選參數(shù),用于給腳本設(shè)置一個(gè)名稱(chēng),便于調(diào)試和錯(cuò)誤消息的輸出。
返回值:
不為0表示有錯(cuò)誤
2、函數(shù)用于調(diào)用Lua函數(shù)并處理其執(zhí)行過(guò)程中可能發(fā)生的錯(cuò)誤
lua_pcall(L,n,r,f)
lua_State *L:Lua狀態(tài)對(duì)象,表示Lua虛擬機(jī)的運(yùn)行實(shí)例。
int nargs:傳遞給Lua函數(shù)的參數(shù)數(shù)量。
int nresults:期望的返回值數(shù)量。
int errfunc:錯(cuò)誤處理函數(shù)在調(diào)用棧中的索引。
返回值:
不為0表示有錯(cuò)誤
3、函數(shù)用于從全局環(huán)境中獲取一個(gè)全局變量,并將其值壓入Lua棧頂
int lua_getglobal(lua_State *L, const char *name)
lua_State *L:Lua狀態(tài)對(duì)象,表示Lua虛擬機(jī)的運(yùn)行實(shí)例。
const char *name:要獲取的全局變量的名稱(chēng)。
4、函數(shù)用于將一個(gè)數(shù)字(lua_Number類(lèi)型)壓入Lua棧頂
void lua_pushnumber(lua_State *L, lua_Number n)
lua_State *L:Lua狀態(tài)對(duì)象,表示Lua虛擬機(jī)的運(yùn)行實(shí)例。
lua_Number n:要壓入棧的數(shù)字。
執(zhí)行流程:
1、加載script腳本加載到lua虛擬機(jī)中
2、將腳本中的my_pow函數(shù),壓入到棧頂
3、壓入my_pow需要的兩個(gè)參數(shù)
4、執(zhí)行腳本
5、獲取腳本中的返回值文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-714985.html
#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
char const *script = R"(
function hello()
print('hello world')
end
function my_pow(x,y)
return x^y
end
)";
char const *script_1 = R"(
pkg.hello()
)";
int main()
{
/*
加載腳本并傳遞參數(shù)
*/
// 創(chuàng)建lua虛擬機(jī),創(chuàng)建虛擬棧
lua_State *state = luaL_newstate();
// 打開(kāi)lua標(biāo)準(zhǔn)庫(kù),以便正常使用lua api
luaL_openlibs(state);
{
// 將lua腳本加載到虛擬機(jī)中,并編譯
auto rst = luaL_loadbuffer(state,script,strlen(script),"hello");
// 判斷是否加載成功
if(rst !=0 ){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script faile:%s\n",msg);
lua_pop(state,-1);
}
return -1;
}
// 執(zhí)行加載并編譯的Lua腳本
if(lua_pcall(state,0,0,0)){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script faile:%s",msg);
lua_pop(state,-1);
}
}
// 從全局環(huán)境中獲取一個(gè)my_pow函數(shù)壓入到棧頂
lua_getglobal(state,"my_pow");
// 判斷棧頂是不是一個(gè)函數(shù),要是不是表示沒(méi)有找到
if(!lua_isfunction(state,-1)){
printf("function named my_pow not function\n");
return -1;
}
// 將數(shù)字參數(shù)壓入Lua棧中
lua_pushnumber(state,2);
lua_pushnumber(state,8);
rst = lua_pcall(state,2,1,0);
if(rst !=0 ){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script faile:%s\n",msg);
lua_pop(state,-1);
}
return -1;
}
if(lua_isnumber(state,-1)){
lua_Number val = lua_tonumber(state,-1);
printf("%lf\n",val);
}
}
lua_close(state);
return 0;
}
2.2、加載腳本到stable(包)
編譯命令: g++ main.cpp -o main -llua -ldl文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-714985.html
#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
char const *script = R"(
function hello()
print('hello world')
end
function my_pow(x,y)
return x^y
end
)";
/*
_G = {
"helloworld" = function print("hello world")
}
_G = {
"pkg" = {
"helloworld" = function print("hello world")
}
}
pkg.helloworld()
*/
char const *script_1 = R"(
pkg.hello()
)";
int main()
{
/*
加載腳本到stable(包)
1、生成chunk push到棧頂
2、創(chuàng)建table,設(shè)置給_G表,_G["pkg"] = {}
3、給這個(gè)table設(shè)置元表,元表繼承_G的訪(fǎng)問(wèn)域(__index)
4、執(zhí)行code chunk
*/
lua_State *state = luaL_newstate();
luaL_openlibs(state);
{
auto rst = luaL_loadbuffer(state,script,strlen(script),"helloworld");
if(rst != 0){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script faile:%s\n",msg);
lua_pop(state,1);
}
return -1;
}
// 取出_G表
lua_getglobal(state,"_G");
if(lua_istable(state,-1)){ // chunk _G
lua_newtable(state); // 創(chuàng)建表 chunk _G new_stable
lua_pushstring(state,"pkg"); // chunk _G new_stable pkg
lua_pushvalue(state,-2); // chunk _G new_stable pkg new_stable
lua_rawset(state,-4); // chunk _G new_stable
char const *upvalueName = lua_setupvalue(state,-3,1); // chunk _G
lua_newtable(state); // chunk _G metastable
lua_pushstring(state,"__index"); // chunk _G metastable "__index"
lua_pushvalue(state,-3); // chunk _G metastable "__index" _G
lua_rawset(state,-3); // chunk _G metastable
lua_pushstring(state,"pkg");
lua_rawget(state,-3); // chunk _G metastable "pkg"(table)
lua_pushvalue(state,-2); // chunk _G metastable pkg(table) metastable
lua_setmetatable(state,-2); // chunk _G metastable pkg(stable)
lua_pop(state,3); // chunk
}
// 執(zhí)行chunk
if(lua_pcall(state,0,0,0)){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("call function chunk failed:%s\n",msg);
lua_pop(state,1);
}
}
// 加載script_1
rst = luaL_loadbuffer(state,script_1,strlen(script_1),"script_1");
if(rst != 0){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script failed:%s\n",msg);
lua_pop(state,1);
}
return -1;
}
if(lua_pcall(state,0,0,0)){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("call function chunk failed:%s\n",msg);
lua_pop(state,1);
}
}
lua_close(state);
}
return 0;
}
2.3、Lua調(diào)用c語(yǔ)言接口
#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
int pow_from_c(lua_State *L)
{
int param_count = lua_gettop(L);
if(param_count != 2)
return 0;
if(lua_isinteger(L,1) && lua_isinteger(L,2)){
auto x = lua_tointeger(L,1);
auto y = lua_tointeger(L,2);
int rst = (int)pow(x,y);
lua_pushinteger(L,rst);
return 1;
}
return 0;
}
char const *script_2 = R"(
local val = pow_from_c(2,3)
print(val)
)";
int main()
{
// lua調(diào)用c語(yǔ)言接口
lua_State *state = luaL_newstate();
luaL_openlibs(state);
{
/*
"_G" = {
"pow_from_c" = pow_from_c
}
*/
lua_getglobal(state,"_G");
lua_pushstring(state,"pow_from_c");
lua_pushcclosure(state,pow_from_c,0); // _G "pow_from_c"; closure
lua_rawset(state,-3); // _G
lua_pop(state,1); // _G
}
auto rst = luaL_loadbuffer(state,script_2,strlen(script_2),"script_2");
if(rst != 0){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script faile:%s\n",msg);
lua_pop(state,1);
}
return -1;
}
if(lua_pcall(state,0,0,0)){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("call function chunk failed:%s\n",msg);
lua_pop(state,1);
}
}
lua_close(state);
return 0;
}
2.4、Lua實(shí)現(xiàn)面向?qū)ο?/h3>
local anial_matestable = {
__index = {
walk = function (self)
print(self,"我是walk")
end,
eat = function (self)
print(self,"eat.")
end,
},
__newindex = function (object,key,value)
print("assigned "..value.."named "..key.."but not really")
end,
}
function newobject()
local objs = {name = "xxxx"}
setmetatable(objs,anial_matestable)
return objs
end
local obj = newobject()
obj.eat()
obj.walk()
obj.name = "abc"
obj.id = 0
2.5、向腳本中注冊(cè)c++的類(lèi)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
char const *script_3 = R"(
local obj_1 = create_game_object(1);
local obj_2 = create_game_object(1);
local obj_3 = create_game_object(2);
local rst1 = obj_1:equal(obj_2)
local rst2 = obj_1:equal(obj_3)
print(rst1,";",rst2)
print(""..obj_1:id())
)";
class GameObject{
private:
u_int32_t _id;
public:
static size_t registy_value;
public:
GameObject(u_int32_t id):_id(id)
{}
u_int32_t id()const{
return _id;
}
bool equal(GameObject *obj){
return _id == obj->id();
}
};
size_t GameObject::registy_value = 0;
int GameObject_equal(lua_State *state){
int arg_count = lua_gettop(state);
if(arg_count!=2){
return 0;
}
if(lua_isuserdata(state,1) && lua_isuserdata(state,2)){
void *userdata_self = lua_touserdata(state,1);
void *userdata_that = lua_touserdata(state,2);
GameObject *obj1 = (GameObject*)userdata_self;
GameObject *obj2 = (GameObject*)userdata_that;
auto rst = obj1->equal(obj2);
lua_pushboolean(state,rst);
return 1;
}
return 0;
}
int GameObject_id(lua_State* state){
GameObject *this_obj = (GameObject*)lua_touserdata(state,1);
auto rst = this_obj->id();
lua_pushinteger(state,rst);
return 1;
}
int create_game_object(lua_State* state){
auto id = lua_tointeger(state,1);
void *p = lua_newuserdata(state,sizeof(GameObject));
GameObject *obj = new(p)GameObject(id);
lua_rawgetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);
lua_setmetatable(state,-2);
return 1;
}
int main()
{
// 怎么向腳本中注冊(cè)c++的類(lèi)
// 使用userdata
/*
userdata:{
metadata:{
__index = {
equal = function(){},
id = function(){},
}
}
}
*/
lua_State *state = luaL_newstate();
luaL_openlibs(state);
{
lua_getglobal(state,"_G");
lua_pushstring(state,"create_game_object");
lua_pushcclosure(state,create_game_object,0);
lua_rawset(state,-3);
lua_pop(state,1);
lua_newtable(state);
lua_pushstring(state,"__index");
lua_newtable(state);
lua_pushstring(state,"equal");
lua_pushcclosure(state,GameObject_equal,0);
lua_rawset(state,-3);
lua_pushstring(state,"id");
lua_pushcclosure(state,GameObject_id,0);
lua_rawset(state,-3);
lua_rawset(state,-3);
lua_rawsetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);
auto rst = luaL_loadbuffer(state,script_3,strlen(script_3),"oop");
if(rst != 0){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script failed:%s\n",msg);
lua_pop(state,1);
}
return -1;
}
// 執(zhí)行
if(lua_pcall(state,0,0,0)){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script failed:%s\n",msg);
lua_pop(state,1);
}
}
}
lua_close(state);
return 0;
}
local anial_matestable = {
__index = {
walk = function (self)
print(self,"我是walk")
end,
eat = function (self)
print(self,"eat.")
end,
},
__newindex = function (object,key,value)
print("assigned "..value.."named "..key.."but not really")
end,
}
function newobject()
local objs = {name = "xxxx"}
setmetatable(objs,anial_matestable)
return objs
end
local obj = newobject()
obj.eat()
obj.walk()
obj.name = "abc"
obj.id = 0
#include <cstdio>
#include <cstring>
#include <cmath>
#include <new>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
char const *script_3 = R"(
local obj_1 = create_game_object(1);
local obj_2 = create_game_object(1);
local obj_3 = create_game_object(2);
local rst1 = obj_1:equal(obj_2)
local rst2 = obj_1:equal(obj_3)
print(rst1,";",rst2)
print(""..obj_1:id())
)";
class GameObject{
private:
u_int32_t _id;
public:
static size_t registy_value;
public:
GameObject(u_int32_t id):_id(id)
{}
u_int32_t id()const{
return _id;
}
bool equal(GameObject *obj){
return _id == obj->id();
}
};
size_t GameObject::registy_value = 0;
int GameObject_equal(lua_State *state){
int arg_count = lua_gettop(state);
if(arg_count!=2){
return 0;
}
if(lua_isuserdata(state,1) && lua_isuserdata(state,2)){
void *userdata_self = lua_touserdata(state,1);
void *userdata_that = lua_touserdata(state,2);
GameObject *obj1 = (GameObject*)userdata_self;
GameObject *obj2 = (GameObject*)userdata_that;
auto rst = obj1->equal(obj2);
lua_pushboolean(state,rst);
return 1;
}
return 0;
}
int GameObject_id(lua_State* state){
GameObject *this_obj = (GameObject*)lua_touserdata(state,1);
auto rst = this_obj->id();
lua_pushinteger(state,rst);
return 1;
}
int create_game_object(lua_State* state){
auto id = lua_tointeger(state,1);
void *p = lua_newuserdata(state,sizeof(GameObject));
GameObject *obj = new(p)GameObject(id);
lua_rawgetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);
lua_setmetatable(state,-2);
return 1;
}
int main()
{
// 怎么向腳本中注冊(cè)c++的類(lèi)
// 使用userdata
/*
userdata:{
metadata:{
__index = {
equal = function(){},
id = function(){},
}
}
}
*/
lua_State *state = luaL_newstate();
luaL_openlibs(state);
{
lua_getglobal(state,"_G");
lua_pushstring(state,"create_game_object");
lua_pushcclosure(state,create_game_object,0);
lua_rawset(state,-3);
lua_pop(state,1);
lua_newtable(state);
lua_pushstring(state,"__index");
lua_newtable(state);
lua_pushstring(state,"equal");
lua_pushcclosure(state,GameObject_equal,0);
lua_rawset(state,-3);
lua_pushstring(state,"id");
lua_pushcclosure(state,GameObject_id,0);
lua_rawset(state,-3);
lua_rawset(state,-3);
lua_rawsetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);
auto rst = luaL_loadbuffer(state,script_3,strlen(script_3),"oop");
if(rst != 0){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script failed:%s\n",msg);
lua_pop(state,1);
}
return -1;
}
// 執(zhí)行
if(lua_pcall(state,0,0,0)){
if(lua_isstring(state,-1)){
auto msg = lua_tostring(state,-1);
printf("load script failed:%s\n",msg);
lua_pop(state,1);
}
}
}
lua_close(state);
return 0;
}
到了這里,關(guān)于Lua與C++交互的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!