轻量脚本语言Lua的配置与cpp调用

⌚Time: 2024-03-07 15:34:09

👨‍💻Author: Jack Ge

Lua是一种功能强大且快速的编程语言,易于学习和使用,并且可以嵌入到应用程序中。

Lua被设计成一种轻量级的可嵌入脚本语言。它被用于各种各样的应用程序,从游戏到web应用程序和图像处理。

lua配置

下载

Lua的官网

https://www.lua.org/start.html

脚本语言的运行需要解释器,Lua5.1.5的解释器下载地址,我选择了win32版本的。只有不到1Mb

https://sourceforge.net/projects/luabinaries/files/5.1.5/Tools%20Executables/

下载后解压,将他的主目录添加到windows系统的PATH环境变量里。

运行lua命令

之后运行cmd,输入lua5.1就能够启动解释器,以交互式的方式运行lua


lua5.1

Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio

>


lua脚本的执行

新建一个example.lua文件,编辑文本


print('hello lua script')

之后使用lua解释器执行


lua5.1 D:\example.lua

hello lua script


可以使用luac程序将lua脚本编译成字节码后执行


luac5.1 -o D:\example.luac D:\example.lua

执行


lua5.1 D:\example.luac

hello lua script


C++调用lua

环境配置

下载Lua的库

windows32版本5.1.5的静态库下载地址

https://sourceforge.net/projects/luabinaries/files/5.1.5/Windows%20Libraries/Static/

我下载了VC11版本,适用于VS2012编译器。下载后解压

使用VS2012新建一个项目,配置项目附加头文件目录为lua库的头文件目录

配置链接库目录为lua静态库文件的目录

添加链接的lua库文件名

我下载的是静态库,所以配置完了,如果你下载的是动态库,需要把动态库文件dll目录添加到系统的PATH环境变量,所以运行时会调用。

错误和警告

编译时出现警告


LINK : warning LNK4098: 默认库“LIBCMT”与其他库的使用冲突;请使用 /NODEFAULTLIB:library

是项目生成配置与库的不一致导致的,在C++代码生成的配置里,运行库有/MT,/MTd,/Md,/MDd四个选项,我使用的是静态库,非debug版本,所以项目配置改成多线程(/MT),之后编译就不会有警告

使用c语言编译器直接包含lua头文件,使用c++编译器包含Lua头文件要使用extern "C" 修饰




extern "C" {

#include <lua.h>

#include <lualib.h>

#include <lauxlib.h>

}

否则会在链接时报错




1>main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl lua_close(struct lua_State *)" (?lua_close@@YAXPAUlua_State@@@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl lua_settop(struct lua_State *,int)" (?lua_settop@@YAXPAUlua_State@@H@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "int __cdecl lua_tointeger(struct lua_State *,int)" (?lua_tointeger@@YAHPAUlua_State@@H@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl lua_pushinteger(struct lua_State *,int)" (?lua_pushinteger@@YAXPAUlua_State@@H@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl lua_getfield(struct lua_State *,int,char const *)" (?lua_getfield@@YAXPAUlua_State@@HPBD@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl lua_call(struct lua_State *,int,int)" (?lua_call@@YAXPAUlua_State@@HH@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "int __cdecl lua_pcall(struct lua_State *,int,int,int)" (?lua_pcall@@YAHPAUlua_State@@HHH@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl luaL_openlibs(struct lua_State *)" (?luaL_openlibs@@YAXPAUlua_State@@@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "int __cdecl luaL_loadfile(struct lua_State *,char const *)" (?luaL_loadfile@@YAHPAUlua_State@@PBD@Z),该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 "struct lua_State * __cdecl luaL_newstate(void)" (?luaL_newstate@@YAPAUlua_State@@XZ),该符号在函数 _main 中被引用

1>c:\users\jack\documents\visual studio 2012\Projects\LuaTest\Debug\LuaTest.exe : fatal error LNK1120: 10 个无法解析的外部命令



这是因为Lua库是使用c语言编写的库,c语言编译器与c++编译器的名称修饰不同导致的错误。

通过使用extern "C"来包含C语言头文件就可以解决问题:

C++编译器会对函数名进行名称修饰(name mangling)以支持函数重载和命名空间等特性。而C语言没有名称修饰的概念。使用extern "C"可以告诉C++编译器,对包含的C语言头文件中的函数名不进行名称修饰,保持它们的原始名称。

实现C和C++的混合编程:C++代码可以通过包含C语言头文件来调用C语言函数。通过extern "C"包装C语言头文件,可以确保C++编译器正确处理C语言函数的声明和调用,避免编译错误。


extern "C" {

    #include "c_header.h"

}

其中,c_header.h是C语言的头文件,extern "C"告诉C++编译器不对该头文件中的函数名进行名称修饰。这样在C++代码中就可以直接使用C语言头文件中的函数了。

测试c++程序

编辑c++源文件,调用lua脚本中的函数比较两个数字的最大值




#include <iostream>

extern "C" {

#include <lua.h>

#include <lualib.h>

#include <lauxlib.h>

}

int main(){

    lua_State *L = luaL_newstate();     //创建Lua状态

    luaL_openlibs(L);                   //打开Lua库



    luaL_dostring(L,"print('hello lua')");//直接执行lua语句

    luaL_dofile(L, "script.lua");       //加载和执行Lua脚本



    lua_getglobal(L, "maxnumber");      // 获取函数引用

    lua_pushinteger(L, 5);              // 添加参数

    lua_pushinteger(L, 6);              // 添加参数

    lua_call(L, 2, 1);                  // 调用函数,2个参数,1个返回值



    int result = lua_tointeger(L, -1);  // 获取返回值

    lua_pop(L, 1);                      // 弹出返回值



    lua_close(L);                       //清理Lua状态



    std::cout<<result;                  //打印结果



    std::cin.get();



    return 0;

}

lua脚本

程序加载的lua脚本有调用的函数

script.lua


function maxnumber(a, b)

    if a > b then

        return a

    else

        return b

    end

end


结果

编译运行程序可以得到输出


hello lua

lua script is executed.

6