日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

lua_tinker源码笔记1

發(fā)布時(shí)間:2025/3/15 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lua_tinker源码笔记1 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本篇僅簡(jiǎn)單介紹使用lua_tinker讓lua調(diào)用C++函數(shù)的過(guò)程, C++調(diào)用lua函數(shù)可以參見(jiàn)博客Lua腳本和C++交互(一).

未完待續(xù).

(一) lua調(diào)用C++全局函數(shù)

這里以lua_tinker自帶的sample1作為分析例子.C++源碼如下:

// sample1.cpp #include "stdafx.h" #include "../lua_tinker/lua_tinker.h"int cpp_func(int arg1, int arg2) {return arg1 + arg2; }int _tmain(int argc, _TCHAR* argv[]) { lua_State* L = lua_open();luaopen_base(L);lua_tinker::def(L, "cpp_func", cpp_func);lua_tinker::dofile(L, "sample1.lua");int result = lua_tinker::call<int>(L, "lua_func", 3, 4);printf("lua_func(3,4) = %d\n", result);lua_close(L);return 0; }

lua文件源碼如下:

-- sample1.lua result = cpp_func(1, 2)print("cpp_func(1,2) = "..result)function lua_func(arg1, arg2)return arg1 + arg2 end

從main函數(shù)開(kāi)始分析. 首先通過(guò)lua_open獲取lua棧對(duì)象,再打開(kāi)lua庫(kù)(luaopen_base). 接下來(lái),lua_tinker::def注冊(cè)一個(gè)C++全局函數(shù),lua_tinker::dofile打開(kāi)lua文件,通過(guò)lua_tinker::call調(diào)用到sample1.lua里面的lua函數(shù).最后關(guān)閉釋放lua棧對(duì)象(lua_close).本文重點(diǎn)在于探究ua_tinker::def如何完成C++全局函數(shù)的注冊(cè).

(1) lua_tinker只有一個(gè).h和.cpp文件,在lua_tinker.h里面,我們找到了上面的函數(shù)調(diào)用,如下:

// global function // lua_tinker::def(L, "cpp_func", cpp_func); template<typename F> void def(lua_State* L, const char* name, F func) { lua_pushstring(L, name);lua_pushlightuserdata(L, func);push_functor(L, func);lua_settable(L, LUA_GLOBALSINDEX); }

在代碼中,我們可以看到,首先將全局函數(shù)名稱"cpp_func"壓入lua棧(), 此時(shí)的lua棧只有這一個(gè)元素且為棧頂, 然后我們?cè)賹⑷趾瘮?shù)對(duì)應(yīng)的函數(shù)指針壓入棧(查lua_reference可以知道,如果是light userdata(而不是full userdata)的話,lua_pushlightuserdata只是簡(jiǎn)單地壓入函數(shù)指針), 此時(shí)的lua棧有兩個(gè)元素,棧頂為func函數(shù)指針,第2個(gè)元素是我們剛才壓入的全局函數(shù)名稱;第3步的push_functor是lua_tinker對(duì)壓入cclosure(c閉包)函數(shù)lua_pushcclosure的一個(gè)封裝,查看此函數(shù):

template<typename RVal, typename T1, typename T2> void push_functor(lua_State *L, RVal (*func)(T1,T2)) { lua_pushcclosure(L, functor<T1,T2>::invoke<RVal>, 1); }

這里涉及到模板函數(shù)的重載,模板相關(guān)知識(shí)參見(jiàn)系列博客C++ template —— 模板基礎(chǔ)(一).這里不做過(guò)多闡述.

上面我們的全局函數(shù)cpp_func是一個(gè)接受兩個(gè)參數(shù)且有一個(gè)返回值的函數(shù),所以我們找到了如上的模板函數(shù), 從代碼中可以看到,push_functor()只是簡(jiǎn)單地調(diào)用lua函數(shù)lua_pushcclosure,但是對(duì)參數(shù)做了一層封裝.lua_pushcclosure接受三個(gè)參數(shù),第2個(gè)參數(shù)表示要壓入的c閉包函數(shù)體(此處為functor結(jié)構(gòu)體的invoke函數(shù)),第3個(gè)參數(shù)表示此c閉包關(guān)聯(lián)的upvalue個(gè)數(shù)(最大255).本例中只有一個(gè)(會(huì)獲取到上面通過(guò)lua_pushlightuserdata壓入的函數(shù)指針), lua_pushcclosure壓入c閉包,同時(shí)會(huì)把所有的upvalue(這里只有函數(shù)指針)全都pop出棧.此時(shí)的lua棧只有兩個(gè)元素,棧頂也就是剛剛壓入的cclosure,下面一個(gè)元素是函數(shù)名稱. 接下來(lái),我們?cè)倏纯磃unctor如何封裝此函數(shù)指針:

template<typename T1, typename T2> struct functor<T1,T2> {template<typename RVal>static int invoke(lua_State *L) { push(L,upvalue_<RVal(*)(T1,T2)>(L)(read<T1>(L,1),read<T2>(L,2))); return 1; }template<>static int invoke<void>(lua_State *L) { upvalue_<void(*)(T1,T2)>(L)(read<T1>(L,1),read<T2>(L,2)); return 0; } };

這里涉及到的是類(結(jié)構(gòu)體)模板和類模板偏特化的內(nèi)容,這里也不做過(guò)多闡述,感興趣同樣可以參見(jiàn)上面模板系列博客.

根據(jù)類模板偏特化,我們找到了上面接收兩個(gè)模板參數(shù)的對(duì)應(yīng)functor代碼,可以看到,invoke執(zhí)行的操作就是將全局函數(shù)壓入棧. upvalue_獲取閉包的upvalue,這里是全局函數(shù)cpp_func的指針,再通過(guò)read指定(cpp_func全局函數(shù)所需要的)兩個(gè)參數(shù),最后通過(guò)push壓入lua棧.upvalue_代碼如下:

// get value from cclosure template<typename T> T upvalue_(lua_State *L) {return user2type<T>::invoke(L, lua_upvalueindex(1)); }

lua_upvalueindex(1)獲取cclosure中的第1個(gè)upvalue,也即全局函數(shù)地址.

最后,通過(guò)lua_settable(L, LUA_GLOBALSINDEX);找到全局表索引位置的全局表t,并以棧頂為value(cclosure),下一個(gè)元素為key(全局函數(shù)名稱),設(shè)置t[key] = value;將封裝過(guò)的元素函數(shù)指針設(shè)置進(jìn)lua全局表里面,這樣,在lua文件sample1.lua中,就可以直接通過(guò)全局函數(shù)名稱"cpp_func"調(diào)用到C++的函數(shù)了.

?

本篇博文為個(gè)人分析,如發(fā)現(xiàn)錯(cuò)誤,請(qǐng)留言指出,共同進(jìn)步,謝謝!

?

?(二) lua調(diào)用C++ 的非全局函數(shù)

[參考]:lua 函數(shù)調(diào)用1 -- 閉包詳解和C調(diào)用

轉(zhuǎn)載于:https://www.cnblogs.com/yyxt/p/5503449.html

總結(jié)

以上是生活随笔為你收集整理的lua_tinker源码笔记1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。