Programming in Lua, 2Nd Edition - Chapter 26: Calling C from Lua

本文详细介绍了如何从Lua环境中调用C语言函数,并通过具体示例展示了注册C函数的过程及注意事项。此外,还介绍了如何将C代码组织为模块以方便Lua调用,并提供了扩展Lua标准库的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

 

 

Chapter 26: Calling C from Lua

 

要从lua 调用一个C 函数,必须注册它,就是说以舍适的方式把函数的地址传给它。C 函数从栈上获取lua 传过来的参数,而函数的返回值也会压入栈中。当lua 调用一个C 函数,第一个参数在栈中的索引总是1.

 

 

26.1 C Functions

 

 

???Any function registered with Lua must have this same prototype, defined as lua_CFunction in lua.h:

 

typedef int (*lua_CFunction) (lua_State *L); ???

 

 

-- version 1

static int l_sin (lua_State *L) {

     double d = lua_tonumber(L, 1); /* get argument */

     lua_pushnumber(L, sin(d)); /* push result */

     return 1; /* number of results */

}

 

-- version 2

static int l_sin (lua_State *L) {

     double d = luaL_checknumber(L, 1);

     lua_pushnumber(L, sin(d));

     return 1; /* number of results */

}

 

lua_pushcfunction(L, l_sin);

lua_setglobal(L, "mysin");

 

luaL_checknumber 检查给定的参数是否是数字,出错抛出message,否则返回数字值。

 

快速测式一个C 函数的方法是将上面的代码全部加入lua.c 文件

 

运行mysin('a') ,会得到错误消息:

 

bad argument #1 to 'mysin' (number expected, got string)

 

 

注意luaL_checknumber 是如何自动填充消息的。

 

 

 

26.2 C Modules

 

Lua 通过注册过程感知道C 函数,之后lua 调用的时侯就直接引用这个函数的地址(我们注册的时侯传给它的)。换句话说,一旦经过注册,Lua 不依赖函数名,包位置,或可见规则。通常,C 模块有一个公有函数用来打开这个库,而其它函数是私有的,以static 关键字声明

 

当你使用C 来扩展lua,将你的代码设计成包是一个好主意,既使只有一个想要注册的函数

 

 

 

 

 

 

扩充lua 库

 

linit.c

static const luaL_Reg lualibs[] = {
{"", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug},
{LUA_MATHLIBNAME, luaopen_my}, /* add a item */
{NULL, NULL}
};


------

lualib.h

/* add signature */

#define LUA_MYLIBNAME "my"
LUALIB_API int (luaopen_my) (lua_State *L);


------

lmylib.c

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

#define lmylib_c
#define LUA_LIB

#include "lua.h"

#include "lauxlib.h"
#include "lualib.h"

#undef PI
#define PI (3.14159265358979323846)
#define RADIANS_PER_DEGREE (PI/180.0)

/* 使用度数制 */
static int my_sin (lua_State *L) {
lua_pushnumber(L, sin(RADIANS_PER_DEGREE * luaL_checknumber(L, 1)));
return 1;
}

static const luaL_Reg mylib[] = {
{"sin",   my_sin},
{NULL, NULL}
};

LUALIB_API int luaopen_my (lua_State *L) {
luaL_register(L, LUA_MYLIBNAME, mylib);
return 1;
}

 

-------
测试


print(my.sin(90))
--> 1

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值