為Lua5.3編寫C模塊簡單示例


為Lua5.3編寫C模塊簡單示例

 

一、編譯安裝Lua5.3

MSVC 命令行安裝腳本:

@echo off
md bin
md lib
md include
cd src

cl /c /nologo /W3 /O2 /Ob1 /Oi /Gs /MD /D_CRT_SECURE_NO_DEPRECATE l*.c
ren lua.obj lua.o
ren luac.obj luac.o
lib /OUT:lua53.lib *.obj
copy lua53.lib ..\lib\lua53.lib
del *.o *.obj *.exp *.lib *.dll *.exe

cl /c /nologo /W3 /O2 /Ob1 /Oi /Gs /MD /D_CRT_SECURE_NO_DEPRECATE /DLUA_BUILD_AS_DLL l*.c
ren lua.obj lua.o
ren luac.obj luac.o
link /DLL /IMPLIB:lua53.lib /OUT:lua53.dll *.obj
link /OUT:lua53.exe lua.o lua53.lib
link /OUT:luac53.exe luac.o *.obj
copy lua53.exp ..\bin\lua53.exp
copy lua53.lib ..\bin\lua53.lib
copy lua53.dll ..\bin\lua53.dll
copy lua53.exe ..\bin\lua53.exe
copy luac53.exe ..\bin\luac53.exe
del *.o *.obj *.exp *.lib *.dll *.exe

copy lauxlib.h ..\include\lauxlib.h
copy lua.h ..\include\lua.h
copy lua.hpp ..\include\lua.hpp
copy luaconf.h ..\include\luaconf.h
copy lualib.h ..\include\lualib.h
cd ..\

 

打開vs開發人員命令提示,執行此腳本,進行編譯。

 

 

生成的目錄文件結構:

 

 

 

使用VS編寫Lua的C模塊時, VS的配置。

 

 

 

C模塊mytest.h頭文件源碼:

/* Start of mytest.h */

#ifndef __MYTEST_H__
#define  __MYTEST_H__

#ifdef __unix__

#define DllExport extern

#else

#define DllExport  __declspec( dllexport )

#endif // __unix__

#ifdef __cplusplus

#include <lua.hpp>

#else

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

#endif // __cplusplus


#ifdef __cplusplus
extern "C" { // 告訴編譯器以C的方式編譯, 防止變量名稱及函數名稱粉碎問題
#endif // __cplusplus


/* 此函數為C庫中的“特殊函數", 在Windows系統中必須使用"__declspec( dllexport )"導出, 在類Unix上使用"extern"導出
 * 通過調用它注冊所有C庫中的函數,並將它們存儲在適當的位置。
 * 此函數的命名規則應遵循:
 * 1、使用"luaopen_"作為前綴。
 * 2、前綴之后的名字將作為"require"的參數, 所以此名字必須和生成的dll同名否則找不到對應的庫
 */
DllExport int luaopen_cl01(lua_State* L);

#ifdef __cplusplus
} /* extern "C" */
#endif // __cplusplus

#endif // __MYTEST_H__

/* End of mytest.h */

 

C模塊mytest.c文件源碼:

/* Start of mytest.c */

#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>

#include "mytest.h"

#ifdef __cplusplus
extern "C" { // 告訴編譯器以C的方式編譯, 防止變量名稱及函數名稱粉碎問題
#endif // __cplusplus

/* 所有注冊給Lua的C函數具有
 * "typedef int (*lua_CFunction) (lua_State *L);"的原型。
 */
static int l_sin(lua_State *L)
{   
    // 如果給定虛擬棧中索引處的元素可以轉換為數字,則返回轉換后的數字,否則報錯。
    double d = luaL_checknumber(L, 1);
    lua_pushnumber(L, sin(d));  /* push result */

    /* 這里可以看出,C可以返回給Lua多個結果,
     * 通過多次調用lua_push*(),之后return返回結果的數量。
     */
    return 1;  /* number of results */
}

/* 需要一個"luaL_Reg"類型的結構體,其中每一個元素對應一個提供給Lua的函數。
 * 每一個元素中包含此函數在Lua中的名字,以及該函數在C庫中的函數指針。
 * 最后一個元素為“哨兵元素”(兩個"NULL"),用於告訴Lua沒有其他的函數需要注冊。
 */
static const struct luaL_Reg cl01[] = {
    {"mysin", l_sin},
    {NULL, NULL}
};

/* 此函數為C庫中的“特殊函數", 在Windows系統中必須使用"__declspec( dllexport )"導出, 在類Unix上使用"extern"導出
 * 通過調用它注冊所有C庫中的函數,並將它們存儲在適當的位置。
 * 此函數的命名規則應遵循:
 * 1、使用"luaopen_"作為前綴。
 * 2、前綴之后的名字將作為"require"的參數, 所以此名字必須和生成的dll同名否則找不到對應的庫
 */
DllExport int luaopen_cl01(lua_State* L)
{
    /* void luaL_newlib (lua_State *L, const luaL_Reg l[]);
     * 創建一個新的"table",並將"l"中所列出的函數注冊為"table"的域。
     */ 
    luaL_newlib(L, cl01);

    return 1;
}

#ifdef __cplusplus
} /* extern "C" */
#endif // __cplusplus

/* End of mytest.c */

 

點擊生成,產生以下文件

 

我們只需要將 cl01.dll 文件,拷貝到Lua的工作目錄下即可。

 

LuaFile1.lua 文件源碼:

--region LuaFile1.lua
--Date
--此文件由[BabeLua]插件自動生成

io.write(string.format("-------->>> %s <<<--------\n", "testing ...")) -- 此函數不會自動換行
local cl01lib = require("cl01")
print("mysin(3.14 /2) result: ", cl01lib.mysin(3.14 /2))


-- 通過調用控制台命令行使程序暫停
-- os.execute("pause")

--endregion

 

 

運行結果現象:

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM