1. 程式人生 > >lua和C++相互交換資料1 【轉】

lua和C++相互交換資料1 【轉】

Lua生來就是為了和C互動的,因此使用C擴充套件Lua或者將Lua嵌入到C當中都是非常流行的做法。要想理解C和Lua的互動方式,首先要回顧一下C語言是如何處理函式引數的。

C函式和引數
大家知道C語言是用匯編實現的,在組合語言中可沒有函式的概念,與函式對應的是叫做子過程的東西,子過程就是一段指令,一個子過程與它呼叫的子過程之間通過棧來進行引數的傳遞互動。在一個子過程在呼叫別的子過程之前,會按照約定的格式將要呼叫的子過程需要的引數入棧,在被呼叫的子過程中,可以按照約定的規則將引數從棧中取出。同理,對於返回值的傳遞也同樣是通過堆疊進行的。C語言約定的引數放入棧中的格式,就是“呼叫慣例”。C語言的函式原型則決定了壓入棧中的引數的數量和型別。

Lua的虛擬堆疊
Lua和C之間的互動巧妙的模擬了C語言的堆疊,Lua和C語言之間的相互呼叫和訪問都通過堆疊來進行,巧妙的解決了不同型別之間變數相互訪問的問題。具體的,我們想象如下一個圖

  +-------+                      +-------+
  |       |                      |       |
  |       |      +-------+       |       |
  |   C   | <==> |       | <==>  |  Lua  |
  | Space |      |Virtual|       | Space |
  |       |      | Stack |       |       |
  |       |      |       |       |       |
  +-------+      +-------+       +-------+


由於C和Lua是不同層次的語言,因此C語言的變數和Lua中的變數以及函式不能直接的互動,我們假定C語言和Lua都有自己的“空間(C Space和Lua Space)”。而這兩個空間之間的互動就通過上圖中的這個虛擬堆疊來解決。為何採用虛擬堆疊的方式來進行互動呢?其目的是在提供強大的靈活性的同時避免互動時兩種語言變數型別的組合爆炸。

C語言讀寫Lua全域性變數(基本型別)
C語言讀取Lua的全域性變數是一種最簡單的操作。通過上圖我們可以猜測到,如果通過C語言讀取Lua中的全域性變數需要兩步:1、將全域性變數從Lua Space壓入虛擬堆疊;2、從堆疊將全域性變數讀取到C語言Space中。在Lua和C的互動中,Lua無法看到和操作虛擬堆疊,僅在C語言中有操作堆疊的權利,因此前面說到的兩步全都是在C語言中完成的。我們看一個簡單的例子


Lua程式碼:
global_var1 = 5;
print("Print global varb from lua", global_var1);


C程式碼:
......
void get_global(lua_State *L)
{
int global_var1;
lua_getglobal(L, "global_var1"); /* 從lua的變數空間中將全域性變數global_var1讀取出來放入虛擬堆疊中 */
global_var1 = lua_tonumber(L, -1); /* 從虛擬堆疊中讀取剛才壓入堆疊的變數,-1表示讀取堆疊最頂端的元素 */

printf("Read global var from C: %d\n", global_var1);
}
......

執行結果:

[email protected] ~/Programming/article_lua $ ./a.out global_var.lua
Print global var from lua  5
Read global_var: 5

Lua中對堆疊的操作都是通過索引來進行的,索引為1表示從棧底數第一個元素,索引為2表示從棧底數第二個元素;同樣也可以使用負數從棧頂開始計算,-1表示從棧頂數第一個元素,-2表示從棧頂數第二個元素。更多堆疊的操作函式請參考lua的官方手冊http://www.lua.org/manual/5.2/manual.html。 同樣從堆疊中獲取元素,除了我們使用的lua_tonumber之外,還有lua_tolstring,lua_toboolean等。
通常情況下在讀取變數之前還需要對堆疊中元素的實際型別做出檢查:

C程式碼:
......
void get_global(lua_State *L)
{
int global_var1;
lua_getglobal(L, "global_var1"); /* 從lua的變數空間中將全域性變數global_var1讀取出來放入虛擬堆疊中 */
if (!lua_isnumber(L, -1))        /* 檢查堆疊中棧頂第一個元素是否是數字 */
error(L, "Is not number.");
global_var1 = lua_tonumber(L, -1); /* 從虛擬堆疊中讀取剛才壓入堆疊的變數,-1表示讀取堆疊最頂端的元素 */
}
......

寫入全域性變數也一樣簡單:
首先將資料壓入堆疊,然後再將堆疊中的資料存入全域性變數。

C程式碼:
void set_global(lua_State *L)
{
lua_pushinteger(L, 9);
lua_setglobal(L, "global_var1");
printf("set global var from C:9\n");
}

執行結果:

[email protected]ypi ~/Programming/article_lua $ ./a.out global_var.lua
set global var from C:9
Print global var from lua       9


相關推薦

luaC++相互交換資料1

Lua生來就是為了和C互動的,因此使用C擴充套件Lua或者將Lua嵌入到C當中都是非常流行的做法。要想理解C和Lua的互動方式,首先要回顧一下C語言是如何處理函式引數的。 C函式和引數 大家知道C語言是用匯編實現的,在組合語言中可沒有函式的概念,與函式對應的是叫做子過程

Redis資料"丟失"討論及規避解決的幾點總結

轉自 https://blog.csdn.net/shangyuanlang/article/details/81297970 Redis大部分應用場景是純快取服務,請求後端有Primary Storage的元件,如MySQL,HBase;請求Redis的鍵未命中,會從primary Sto

objective-c基本資料型別

1、Object-c提供基本資料型別:int、float 、double 、char     示例程式碼測位元組數: //資料型別:         //整形(int、short int、long int、unsigned int、unsigned shor

C++中的異常安全性

div 現實 操作 ... 基本 數據 安全性 異常安全 做的 原文寫的非常好,來自這裏 一個函數如果說是“異常安全”的,必須同時滿足以下兩個條件:1.不泄漏任何資源;2.不允許破壞數據。 我們先通過兩個反面的例子開始。 第一個是造成資源泄漏的例子。一個類Ty

rabbitmqkafka怎麽選?

流式 src 讀取數據 內部 zero-copy 丟失 簡單 好的 項目 MQ框架非常之多,今天簡單說一下有代表性的兩個MQ(rabbitmq和kafka)。經常會有人問rabbitmq和kafka到底哪個好呢?其實沒有好與不好之分,只有哪個更合適,首先要根據自己項目的業務

C#中的數組

常用屬性 創建 ++ 返回 foreach 限制 允許 [] 總數 目錄 數組的聲明 數組的初始化 數組的訪問 數組的常用屬性和方法   為方便起見,以下數組均定義為整型   數組的聲明     C#聲明數組時,方括號[]必須跟

python time模塊datetime模塊詳解

-a cond .com ima 封裝 基本 sta times %d 一、time模塊 time模塊中時間表現的格式主要有三種:   a、timestamp時間戳,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量   b、struct_time時間

S0.1 調色板

table 處理 能力 baidu www. 圖像處理 disk 真彩色 行為 摘自《數字圖像處理編程入門》 我發在csdn下載區了, 作為免費資源,傳送:《數字圖像處理編程入門》 csdn不允許免費資源了,微盤鏈接:《數字圖像處理編程入門》 舉例說明調色板 有一個長寬各為

程序/執行緒同步的方式機制,程序間通訊

(轉自:https://www.cnblogs.com/virusolf/p/5331946.html) 一、程序/執行緒間同步機制。 臨界區、互斥區、事件、訊號量四種方式臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)的區別

C++中STL用法總結

(轉自:https://blog.csdn.net/piaoxuezhong/article/details/54348787?utm_source=blogxgwz8) 1.1 什麼是STL? STL(Standard Template Library),即標準模板庫,是一個具有工業強度的

C++ vector型別要點總結

(轉自:https://blog.csdn.net/suool/article/details/13295439?utm_source=blogxgwz22)   概述 C++內建的陣列支援容器的機制,但是它不支援容器抽象的語義。要解決此問題我們自己實現這樣的類。在標準C++中

C++中的::的作用

(轉自:https://blog.csdn.net/zhanghuaichao/article/details/55676209?utm_source=blogxgwz0) (1)作用域限定符,當在類體中直接定義函式時,不需要在函式名字的前面加上類名,但是在類體外實現函式定義的時候,必須加上類名

機器學習資料

500款各領域機器學習資料集,總有一個是你要找的 金融 美國勞工部統計局官方釋出資料:http://dataju.cn/Dataju/web/datasetInstanceDetail/139 滬深股票除權除息、配股增發全量資料,截止 2016.12.31 http://dataju.c

UFS 介紹 1[

本文轉載自:https://blog.csdn.net/u014645605/article/details/52063624 硬體架構:介面示意圖:UFS 速度和emmc的對比    UFS2.1    UFS2.0   &n

C++中的mutable關鍵字

mutalbe的中文意思是“可變的,易變的”,跟constant(既C++中的const)是反義詞。     在C++中,mutable也是為了突破const的限制而設定的。被mutable修飾的變數,將永遠處於可變的狀態,即使在一個const函式中。     我們知道,

ibevent libev 提高網路應用效能

轉自:https://www.cnblogs.com/kunhu/p/3632285.html 構建現代的伺服器應用程式需要以某種方法同時接收數百、數千甚至數萬個事件,無論它們是內部請求還是網路連線,都要有效地處理它們的操作。有許多解決方 案,但是 libevent 庫和 libev 庫能夠大大提高效能和事

一個易錯的面試題來加深對C++多型的理解

    原題目程式比較長, 我來簡化成核心的考察部分, 如下: #include <iostream> using namespace std; class A { public: virtual void x() { cout <<

CDMA、GSM模組串列埠RTSCTS硬體流控制小結

    後來隨著串列埠裝置的越來越多,其中更多的裝置是屬於非RS232標準的,即不完全符合RS232各腳定義的裝置。這時候為了適應這種變化,計算機廠商便把RS232標準轉換為UART標準,U即為通用的意思。原來9根線都有明確定義的RS232匯流排變成了即可以接受RS232標準又可以接受不符合RS232標準的

C# 委託的妙文

今天看到一個講委託講的通俗易懂的文章,記錄之 出處 委託和事件在 .Net Framework中的應用非常廣泛,然而,較好地理解委託和事件對很多接觸C#時間不長的人來說並不容易。它們就像是一道檻兒,過了這個檻的人,覺得真是太容易了,而沒有過去的人每次見到委託和

Jmeter解決從csv引數檔案中獲取帶引號/逗號的資料問題

原文:【jmeter隨筆(3)-從csv中獲取帶引號的資料詳情】  點選檢視原文 作者:黑夜小怪 軟體測試技術交流群 : 429183023  最近在工作中,對jmeter實踐的點滴的記錄這裡分享,不一定正確,僅供參考和討論,有想法的歡迎留言、談論。 1技巧