1. 程式人生 > >Step By Step(Lua呼叫C函式)

Step By Step(Lua呼叫C函式)

Lua可以呼叫C函式的能力將極大的提高Lua的可擴充套件性和可用性。對於有些和作業系統相關的功能,或者是對效率要求較高的模組,我們完全可以通過C函式來實現,之後再通過Lua呼叫指定的C函式。對於那些可被Lua呼叫的C函式而言,其介面必須遵循Lua要求的形式,即typedef int (*lua_CFunction)(lua_State* L)。簡單說明一下,該函式型別僅僅包含一個表示Lua環境的指標作為其唯一的引數,實現者可以通過該指標進一步獲取Lua程式碼中實際傳入的引數。返回值是整型,表示該C函式將返回給Lua程式碼的返回值數量,如果沒有返回值,則return 0即可。需要說明的是,C函式無法直接將真正的返回值返回給Lua程式碼,而是通過虛擬棧來傳遞Lua程式碼和C函式之間的呼叫引數和返回值的。這裡我們將介紹兩種Lua呼叫C函式的規則。

    1. C函式作為應用程式的一部分。

#include <stdio.h>
#include <string.h>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>

//待Lua呼叫的C註冊函式。
static int add2(lua_State* L)
{
    //檢查棧中的引數是否合法,1表示Lua呼叫時的第一個引數(從左到右),依此類推。
    //如果Lua程式碼在呼叫時傳遞的引數不為number,該函式將報錯並終止程式的執行。
    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);
    //將函式的結果壓入棧中。如果有多個返回值,可以在這裡多次壓入棧中。
    lua_pushnumber(L,op1 + op2);
    //返回值用於提示該C函式的返回值數量,即壓入棧中的返回值數量。
    return 1;
}

//另一個待Lua呼叫的C註冊函式。
static int sub2(lua_State* L)
{
    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);
    lua_pushnumber(L,op1 - op2);
    return 1;
}

const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))";

int main()
{
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);
    //將指定的函式註冊為Lua的全域性函式變數,其中第一個字串引數為Lua程式碼
    //在呼叫C函式時使用的全域性函式名,第二個引數為實際C函式的指標。
    lua_register(L, "add2", add2);
    lua_register(L, "sub2", sub2);
    //在註冊完所有的C函式之後,即可在Lua的程式碼塊中使用這些已經註冊的C函數了。
    if (luaL_dostring(L,testfunc))
        printf("Failed to invoke.\n");
    lua_close(L);
    return 0;
}

2. C函式庫成為Lua的模組。
    將包含C函式的程式碼生成庫檔案,如Linux的so,或Windows的DLL,同時拷貝到Lua程式碼所在的當前目錄,或者是LUA_CPATH環境變數所指向的目錄,以便於Lua解析器可以正確定位到他們。在我當前的Windows系統中,我將其copy到"C:\Program Files\Lua\5.1\clibs\",這裡包含了所有Lua可呼叫的C庫。見如下C語言程式碼和關鍵性註釋:
#include <stdio.h>
#include <string.h>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>

//待註冊的C函式,該函式的宣告形式在上面的例子中已經給出。
//需要說明的是,該函式必須以C的形式被匯出,因此extern "C"是必須的。
//函式程式碼和上例相同,這裡不再贅述。
extern "C" int add(lua_State* L) 
{
    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);
    lua_pushnumber(L,op1 + op2);
    return 1;
}

extern "C" int sub(lua_State* L)
{
    double op1 = luaL_checknumber(L,1);
    double op2 = luaL_checknumber(L,2);
    lua_pushnumber(L,op1 - op2);
    return 1;
}

//luaL_Reg結構體的第一個欄位為字串,在註冊時用於通知Lua該函式的名字。
//第一個欄位為C函式指標。
//結構體陣列中的最後一個元素的兩個欄位均為NULL,用於提示Lua註冊函式已經到達陣列的末尾。
static luaL_Reg mylibs[] = { 
    {"add", add},
    {"sub", sub},
    {NULL, NULL} 
}; 

//該C庫的唯一入口函式。其函式簽名等同於上面的註冊函式。見如下幾點說明:
//1. 我們可以將該函式簡單的理解為模組的工廠函式。
//2. 其函式名必須為luaopen_xxx,其中xxx表示library名稱。Lua程式碼require "xxx"需要與之對應。
//3. 在luaL_register的呼叫中,其第一個字串引數為模組名"xxx",第二個引數為待註冊函式的陣列。
//4. 需要強調的是,所有需要用到"xxx"的程式碼,不論C還是Lua,都必須保持一致,這是Lua的約定,
//   否則將無法呼叫。
extern "C" __declspec(dllexport)
int luaopen_mytestlib(lua_State* L) 
{
    const char* libName = "mytestlib";
    luaL_register(L,libName,mylibs);
    return 1;
}

 見如下Lua程式碼:
require "mytestlib"  --指定包名稱

--在呼叫時,必須是package.function
print(mytestlib.add(1.0,2.0))
print(mytestlib.sub(20.1,19))

原文:http://www.cnblogs.com/stephen-liu74/archive/2012/07/23/2469902.html

相關推薦

Step By Step(Lua呼叫C函式)

Lua可以呼叫C函式的能力將極大的提高Lua的可擴充套件性和可用性。對於有些和作業系統相關的功能,或者是對效率要求較高的模組,我們完全可以通過C函式來實現,之後再通過Lua呼叫指定的C函式。對於那些可被Lua呼叫的C函式而言,其介面必須遵循Lua要求的形式,即typedef

Step By Step(Lua調用C函數)

extern lua環境 class 數量 lsp 相同 虛擬 c語言代碼 cti 原文: http://www.cnblogs.com/stephen-liu74/archive/2012/07/23/2469902.html Lua可以調用C函數的能力將極大的提高Lu

Step By Step(Lua目錄)

處理 叠代 類型 引用 持久化 系統 for 聲明 錯誤處理 Step By Step(Lua開篇)http://www.cnblogs.com/stephen-liu74/archive/2012/03/17/2403210.html一、簡介二、主要優勢三、應用場景Ste

[轉]RDL(C) Report Design Step by Step 3: Mail Label

設置 ted 運算 lec 標題 report 對數 win 信息管理 本文轉自:http://www.cnblogs.com/waxdoll/archive/2006/09/02/493350.html Crystal Report在報表向導中提供了三種向導類型給用戶

luaC 函式呼叫Lua函式時,對於lua_pcall使用的困惑

最近在學習使用Lua,也通過基本的語法知識完成了公司的一個關於配置檔案引數合法性檢查的小任務。雖然任務完成了,但對於一些函式的呼叫目的還是搞不明白,這兩天再次重看了Manual Reference,稍微梳理出了一點眉目,記錄在此。 首先看一段小小小程式 fun

luac/c++ 互動(6) lua呼叫C++(使用陣列 和字串函式

lua呼叫 c++ 的 兩個函式: 一個是 對lua 陣列 呼叫函式替換 陣列元素,一個 分割字串 test.lua --陣列操作 a = {1,2,3,4,5,6} swapArray(a,function(t) return t + 1 end) local

Step By Step(Lua元表與元方法)

 Lua中提供的元表是用於幫助Lua資料變數完成某些非預定義功能的個性化行為,如兩個table的相加。假設a和b都是table,通過元表可以定義如何計算表示式a+b。當Lua試圖將兩個table相加時,它會先檢查兩者之一是否有元表,然後檢查該元表中是否存在__add欄位,

Step By Step(Lua編譯執行與錯誤)

    1. 編譯:     Lua中提供了dofile函式,它是一種內建的操作,用於執行Lua程式碼塊。但實際上dofile只是一個輔助函式,loadfile才是真正的核心函式。相比於dofile,loadfile只是從指定的檔案中載入Lua程式碼塊,然後編譯這段程式碼

Step By Step(Lua模組與包)

    從Lua 5.1開始,我們可以使用require和module函式來獲取和建立Lua中的模組。從使用者的角度來看,一個模組就是一個程式庫,可以通過require來載入,之後便得到一個型別為table的全域性變數。此時的table就像名字空間一樣,可以訪問其中的函式

Linux系統呼叫圖解(摘自《Assebly Language Step by Step》)

有圖有真相,這個是目前我找到的解釋Linux系統呼叫機制的最好圖解。 1 INT 80H 指令導致軟中斷,儲存下一條指令地址到棧,IP暫存器裝入80H號中斷向量,進入Linux系統服務分配器。 2 IRET 指令,之前儲存到棧中的地址出棧賦給IP,中

8、Lua呼叫C++函式

    來往來往,有來有往才能叫做來往。既然C/C++和lua是好親戚,那就會有來有往。之前,我們一直在討論在C/C++中如何使用Lua提供的變數和函式。從這篇文章開始,咱們來討論一下如何在Lua中使用C/C++提供的變數、函式甚至類。     當然,我們還是

Makefile新手向教程:跟著+c同學step by step寫makefile

前言 最近在寫底層C程式碼需要用到makefile來簡化編譯流程並優化檔案目錄結構,一直沒找到很好的makefile教程(一個通俗易懂的漸進式的教程),通過+c同學終於是找到了他在之前在學校實訓的時候寫的一篇文章,由於網站只能通過校內網查閱,在此決定分享一下,

VmWare 與 宿主主機通信 STEP BY STEP (適用於剛開始學習的人)

aid 並且 cap 應該 行程 最大的 mtu win7 bringing 基本原理 在虛擬機中有三種通信方式,例如以下圖所看到的 1. Bridged(橋接模式) 在橋接模式下,VMware虛擬出來的操作系統就像是局域網中的一獨立的主機

學習mybatis-3 step by step 篇一

odi png environ factor 數據 不能 val 集成開發環境 start 一、搭建簡單mybatis-3環境(詳細的中文文檔) 集成開發環境:IDEA 項目:maven + mybatis-3 1、創建maven結構項目 含簡單,如下圖: 下一步後,填寫

Angular4 step by step.3

pen 分享 -1 edi sco lar ide mod code 1.Routes 路由模塊 1 import { NgModule } from [email protected]/* *//core‘; 2 import

WPF Step By Step 系列 - 開篇

gpu 查看 這一 order 界面設計 基礎知識 http 對比 快速 WPF 系列包含的內容 WPF基礎知識介紹 WPF布局介紹 WPF控件介紹(包含第三方控件) WPF自定義模板 WPF依賴屬性、路由事件 WPF的MVVM編程 WPF開發框架Prism WPF開

Quartz.NET開源作業調度框架系列(一):快速入門step by step-轉

rand 隨機 axis 開發人員 c# returns .net開源 觸發 mis  Quartz.NET是一個被廣泛使用的開源作業調度框架 , 由於是用C#語言創建,可方便的用於winform和asp.net應用程序中。Quartz.NET提供了巨大的靈活性但又兼具

Building your Deep Neural Network: Step by Step

pan auto plot chan arr src computing zeros rect Welcome to your week 4 assignment (part 1 of 2)! You have previously trained a 2-layer N

Step By Step 搭建 MySql MHA 集群

ip add 環境 def text 初始化 下載 git 下載源碼 恢復 關於MHA ?? MHA(Master High Availability)是一款開源的mysql高可用程序,目前在mysql高可用方面是一個相對成熟的解決方案。MHA 搭建的前提是MySQL集群中

Struts2+Spring+Hibernate step by step 06 整合Hibernate

emp 2.3 是否 ssh整合 配置 pla sets 映射類 veh 註:該系列教程。部分內容來自王健老師編寫ssh整合開發教程 Hibernate是一款優秀的ORM(Object Relation Mapping-對