糖果实验室杂货铺

Candy Lab

《Lua游戏AI开发指南 --- C/C++中调用Lua函数》

2 years ago 0

C/C++ calling Lua functions

The sandbox hooks into the Lua script through three predefined global Lua functions:

SandboxInitialize, SandboxCleanup, and Sandbox_Update. When the sandbox is first

attached to the corresponding Lua script, the Sandbox_Initialize function is called. Each

update tick of the sandbox will also invoke the Sandbox_Update function in the Lua script.

When the sandbox is being destroyed or reloaded, the Sandbox_Cleanup function will

have an opportunity to perform any script-side cleanup.

In order for C++ to call a Lua function, the function must be retrieved from Lua and

pushed onto the stack. Function parameters are then pushed on top of the stack, followed

by a call to luapcall, which executes the Lua function. The luapcall function

specifies the number of arguments the Lua function receives, the number of expected

return values, and specifies how to handle errors:

lua.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int lua_pcall(

lua_State* luaVM, int numberOfArguments,

int numberOfResults, int errorFunction);

For example, the Agent_Initialize Lua script function is called in the AgentUtilities

class in the following manner:

Agent.lua

function Agent_Initialize(agent)

...

end

First, the Lua function is retrieved from Lua by name and pushed onto the stack. Next, the

agent itself is pushed as the only parameter to the Agent_Initialize function. Lastly,

lua_pcall executes the function and checks whether it succeeded successfully; otherwise,

an assertion is raised by the sandbox:

AgentUtilities.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void AgentUtilities::Initialize(Agent* const agent)

{

// Retrieves the lua virtual machine the agent script is

// running on. lua_State* luaVM = agent->GetLuaVM();

lua_getglobal(luaVM, "Agent_Initialize");

// Agent_Initialize accepts one parameter, an Agent.

AgentUtilities::PushAgent(luaVM, agent);

// Execute the Agent_Initialize function and check for

// success.

if (lua_pcall(luaVM, 1, 0, 0) != 0)

{

assert(false);

}

}

“C/C++中调用Lua函数”

Lua脚本的沙盒钩子是通过预先定义了三个全局的Lua函数:

1.Sandbox_Initalize。

2.Sandboxk_Cleanup。

3.Sandbox_Update。

当沙盒首次载入对应的Lua脚本,SandboxInitialize函数被调用。每次有所更新,沙盒调用脚本中内SandboxUpdate函数。当沙盒初建,或重新载入时,Sanbox_Cleanup函数,有机会执行任何脚本端的清理工作。

C++调用Lua函数,函数要从Lua中取得,并入栈,其参数要入栈顶,之后,用luapacall执行对应Lua函数。luapcall指定Lua函数接受的参数个数,返回值个数和容错处理。

lua.h

1
2
3
int lua_pcall(lua_State* luaVM, int numberOfArguments,

int numberOfResults, int errorFunction);

例如,“Agent_Initialize”脚本函数,被在“AgentUtilities”类中调用,脚本如下:

Agent.lua

1
2
3
4
5
function Agent_Initialize(agent)

...

end

首先,用函数名取得Lua函数,并入栈。

然后,"agen"作为唯一参数,赋给Agent_Initialize函数。

最后,用lua_pcall执行函数,并验证是否成功;

其他情况,会抛出一个沙盒的失败断言“assert(false)”。

AgentUtilities.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void AgentUtilities::Initialize(Agent* const agent)

{

“取得一个agent脚本的运行虚拟机。”

// Retrieves the lua virtual machine the agent script is running on. 

lua_State* luaVM = agent->GetLuaVM();

lua_getglobal(luaVM, "Agent_Initialize");

// Agent_Initialize accepts one parameter, an Agent.

“Agent_Initialize函数接收的参数,“agent”。”

AgentUtilities::PushAgent(luaVM, agent);

“执行Agent_Initialize函数,并验证是否成功。”

// Execute the Agent_Initialize function and check for success.

if (lua_pcall(luaVM, 1, 0, 0) != 0) 

{

assert(false);

}

}

本文译自David Young《Lua游戏AI开发指南》一书。

翻译:糖果

PS:转载到其它平台请注明作者姓名及原文链接。

别动我代码可以不 别动我代码可以不


糖果实验室

Openresty中文编程网
IKBC经典机械键盘
机械键盘领券优惠购买

Write a Comment