1.版本
1.1vs版本
vs2013
1.2lua版本
lua5.1,用luaForWindow安装
2.c调用lua
2.1编写lua代码
callLuaTest.lua
function add(a,b)
return a+b;
end
function sub(a,b)
return a-b;
end
然后把lua文件复制到项目目录下。
2.2复制头文件
vs创建控制台程序,在lua的安装目录下有个include文件夹,里面含有C API的相关头文件,我的路径为C:\Program Files (x86)\Lua\5.1\include,
将它们都复制到项目目录下,添加进工程里。
2.3添加lib库文件
在lua安装目录下有个lib文件夹,有这么些文件,
我们把lua5.1.lib或者lua51.lib复制到项目目录下,这里我选择用lua51.lib。
然后将lua51.lib添加到工程里,具体就是在项目上右击属性-》链接器-》输入-》附加依赖项。
最终我们的工程目录下应该是这样的:
2.4编写C++代码
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string>
#include "lua.hpp"
float add(lua_State* L,float a, float b){
//压入函数和参数
lua_getglobal(L, "add"); //待调用的函数
lua_pushnumber(L, a);//压入第一个参数
lua_pushnumber(L, b);//压入第二个参数
std::string strError;
float fResult=0;
//完成调用(2个参数,一个返回值)
if (lua_pcall(L, 2, 1, 0) != 0)
{
luaL_error(L, "error running function 'f':%s", lua_tostring(L, -1));
}
//检索返回值
if (!lua_isnumber(L, -1))
luaL_error(L, "function 'f' must return a number");
fResult = lua_tonumber(L, -1);
//弹出返回值
lua_pop(L, 1);
return fResult;
}
float sub(lua_State* L, float a, float b){
lua_getglobal(L, "sub");
lua_pushnumber(L, a);
lua_pushnumber(L, b);
std::string strError;
float fResult = 0;
if (lua_pcall(L, 2, 1, 0) != 0)
{
luaL_error(L, "error running function 'f':%s", lua_tostring(L, -1));
}
if (!lua_isnumber(L, -1))
luaL_error(L, "function 'f' must return a number");
fResult = lua_tonumber(L, -1);
lua_pop(L, 1);
return fResult;
}
int _tmain(int argc, _TCHAR* argv[])
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L, "callLuaTest.lua");
float fRes = add(L,1, 2);
std::cout << "add result is " << fRes << std::endl;
fRes = sub(L, 2, 1);
std::cout << "sub result is " << fRes << std::endl;
lua_close(L);
system("pause");
return 0;
}
编译一遍后,会生成Debug文件夹,里面会生成exe文件。
确认lua51.dll,lua5.1.dll的路径都添加环境变量PATH里面,让exe程序可以访问到,否则的话需要将这两个文件复制到Debug文件夹下,和exe文件处于同一下目录。因为我们使用的是lua51.lib,所以需要复制两个dll,假如使用的是lua5.1.lib,只需要复制lua5.1.dll就行了。两个lib的区别看这:
lua51.dll,lua51.lib 和 lua5.1.dll 和lua5.1.lib 的区别
运行程序后输出:
2.5代码分析
在调用lua_pcall时,第二个参数是传给待调用参数的参数数量,第三个参数是期望的结果数量,第四个参数是一个错误处理函数的索引。就像lua的赋值一样,lua_pcall会根据要求的数量来调整实际结果的数量,即压入nil或丢弃多余的结果。在压入结果前,lua_pcall会先删除栈中的函数及其参数。如果一个函数会返回多个结果,那么第一个结果最先压入。例如,函数返回了3个结果,第一个的索引就是-3,最后一个的索引是-1。
如果在lua_pcall的运行过程中有任何错误,lua_pcall会返回一个非零值,并在栈中压入一条错误信息。不过即便如此,它仍会弹出函数及其参数。在压入错误消息前,如果存在一个错误处理函数,lua_pcall就会先调用它。通过lua_pcall的最后一个参数指定这个错误处理函数。零表示没有错误处理函数,那么最终的错误消息就是原来的消息。若传入非零参数,那么这个参数就应该是一个错误处理函数在栈中的索引。因此错误处理函数必须先压入栈中,也就是必须位于待调用函数及其参数的下面。
具体内容可以看《lua程序设计(第2版)》第25章的内容。