为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
运行结果现象: