缘起

luaL_setfuncs 这个函数可以注册c函数到lua,另外还可以设置闭包函数使用的变量upvalue. 我没有用过,在 云风的skynet 才第一次见过,于是写个例子实际使用以下.

函数原型:

void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);

文档定义:

Registers all functions in the array l (see luaL_Reg) into the table on the top of the stack (below optional upvalues, see next).

When nup is not zero, all functions are created sharing nup upvalues, which must be previously pushed on the stack on top of the library table. These values are popped from the stack after the registration.

意思是第三个参数 nup 如果非零, 则所有通过luaL_setfuncs注册的函数都共享 nup个 upvalues. 这些 upvalues 必须在注册之前 pushed 到栈上.

实例

实例是在lua5.3环境下面,编写导处的一个lua能用动态库.

环境搭建

我用的centos7.0,自带lua5.1.下载5.3源码并编译

wget https://www.lua.org/ftp/lua-5.3.4.tar.gz
tar -xzvf lua-5.3.4.tar.gz
cd lua-5.3.4
make linux
编写要导出的lua库
lua_mytest.c
#include <lua.h>
#include <lauxlib.h> static int add(lua_State *L){
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
//将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
lua_pushnumber(L,op1 + op2);
//返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
return 1;
} static int add_with_upvalue(lua_State *L){
int k = lua_tonumber(L, lua_upvalueindex(1));
const char* another_upvalue = lua_tostring(L, lua_upvalueindex(2));
printf("second upvalue is %s\n",another_upvalue); double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
//将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
lua_pushnumber(L,op1 + op2+k);
//返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
return 1;
} static const luaL_Reg no_upvalue_func[] = {
{"add", add},
{0, 0}
}; static const luaL_Reg with_upvalue_func[] = {
{"add_with_upvalue", add_with_upvalue},
{0, 0}
};
LUALIB_API int luaopen_mytest(lua_State * L) {
lua_newtable(L);
/*register function no upvalue*/
luaL_setfuncs(L, no_upvalue_func, 0); /*set two upvalue */
lua_pushnumber(L,100);
lua_pushstring(L,"i am upvalue");
/*register function with two upvalue*/
/*push了两个upvalue值所以第三个参数是2*/
luaL_setfuncs(L, with_upvalue_func, 2);
return 1;
}
MyMakeFile 编译mytest.so
all:
gcc -Wall -O2 -shared -o mytest.so lua_mytest.c -fPIC -llua -I. -lm -L/home/gsx/work/lua_study/lua-5.3.4/src
clean:
rm -f mytest.so

执行命令 make -f MyMakeFile ,生成mytest.so

test.lua
local mytest = require "mytest"

ret = mytest.add(10,20)
print(ret) ret = mytest.add_with_upvalue(10,20)
print(ret)
测试
lua test.lua
output:
30.0
second upvalue is i am upvalue
130.0
注意事项
  1. test.lua 和 mytest.so放在同一个目录.
  2. 如果编译mytest.so的过程中报错. /usr/bin/ld: /usr/local/lib/liblua.a(lapi.o): relocation R_X86_64_32 against `luaO_nilobject_' can not be used when making a shared object; recompile with -fPIC /usr/local/lib/liblua.a: could not read symbols: Bad value, 则重新编译 liblua.a,在 lua的MakeFile 的CFLAG里面增加 -fPIC即可.

总结

例子通过注册一个不带有upvalue和带有两个upvalue的简单函数说明了luaL_setfuncs的作用.

lua5.3中luaL_setfunc设置upvalue的用法示例的更多相关文章

  1. python中的随机函数random的用法示例

    python中的随机函数random的用法示例 一.random模块简介 Python标准库中的random函数,可以生成随机浮点数.整数.字符串,甚至帮助你随机选择列表序列中的一个元素,打乱一组数据 ...

  2. STL中map,set的基本用法示例

    本文主要是使用了STL中德map和set两个容器,使用了它们本身的一些功能函数(包括迭代器),介绍了它们的基本使用方式,是一个使用熟悉的过程. map的基本使用: #include "std ...

  3. 用 SwitchHosts设置hotst, 用法示例

    涉及到本地默认ip(localhost,127.0.0.1)设置关联地址时,使用XAMPP本地服务器时避免自动跳转设置的域名的一些处理方法 打开此文件,把内容修改如下 # Virtual Hosts# ...

  4. 标准C++中的string类的用法总结

    标准C++中的string类的用法总结 相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有 ...

  5. 【转】java.util.vector中的vector的详细用法

    [转]java.util.vector中的vector的详细用法 ArrayList会比Vector快,他是非同步的,如果设计涉及到多线程,还是用Vector比较好一些 import java.uti ...

  6. jquery中attr()与prop()函数用法实例详解(附用法区别)

    本文实例讲述了jQuery中attr()与prop()函数用法.分享给大家供大家参考,具体如下: 一.jQuery的attr()方法 jquery中用attr()方法来获取和设置元素属性,attr是a ...

  7. oracle中to_date详细用法示例(oracle日期格式转换)

    这篇文章主要介绍了oracle中to_date详细用法示例,包括期和字符转换函数用法.字符串和时间互转.求某天是星期几.两个日期间的天数.月份差等用法 TO_DATE格式(以时间:2007-11-02 ...

  8. .NET中代理服务器WebProxy的各种用法

    引用地址 引用 因为涉及到代理的各种情况,WebRequest和WebProxy类的文档写的相当复杂,不但各个文档关注点不同,而且不同版本的同一文档也有小小的区别,网上也没有关于这个类的相关文章.于是 ...

  9. Vue基础01vue的基本示例,vue的双向数据绑定,vue中常见的几种用法,vue相关常见指令

    自学vue框架,每天记录重要的知识点,与大家分享!有不足之处,希望大家指正. 本篇将讲述:vue的基本示例,vue的双向数据绑定,vue中常见的几种用法,vue相关常见指令 前期学习基础,使用vue. ...

随机推荐

  1. R语言中获取当前目录

    # 获取当前工作目录 getwd() # 设置工作目录 setwd()

  2. Efficient data transfer through zero copy

    Efficient data transfer through zero copy https://www.ibm.com/developerworks/library/j-zerocopy/ Eff ...

  3. [报错]Fast enumeration variables cannot be modified in ARC by default; declare the variable __strong to allow this

    今天写了下面的快速枚举for循环代码,从按钮数组subButtons中取出button,然后修改button的样式,在添加到view中 for (UIButton *button in subButt ...

  4. 前端开发 - HTML - 总结

    html head标签 title 显示网站的标题 meta 提供有关页面的原信息 link 链接css资源文件.网站图标 style 定义内部样式表 script 链接脚本js文件 body标签 块 ...

  5. Soldier and Number Game---cf546D(打表求n的素因子个数)

    题目链接:http://codeforces.com/problemset/problem/546/D 题意: 给出一个n,n开始是a!/b!,每次用一个x去整除n得到新的n,最后当n变成1的时候经过 ...

  6. ubuntu安装mysql步骤

    https://dev.mysql.com/downloads/file/?id=477124 ubuntu上安装mysql非常简单只需要几条命令就可以完成. 1. sudo apt-get inst ...

  7. 【我的Android进阶之旅】Android 7.0报异常:java.lang.SecurityException: COLUMN_LOCAL_FILENAME is deprecated;

    之前开发的一个和第三方合作的apk,在之前公司的 Android 5.1 系统的手表上运行正常,今天在公司新开发的 Android 7.1系统的手表上运行的时候,使用 DownloadManager ...

  8. myeclipse自动设置类和方法的注释(快捷键)

    类的注释 第一步:找到Window→Preferences→Java→Code Style→Code Templates→Comments→Types 第二步:编辑Pattern,我一般用的模板 /* ...

  9. django 用户注册功能实现

    增加views的类 class RegisterView(View): def get(self, request): return render(request, 'register.html', ...

  10. oracle dataguard参数

    在整个dg配置中,最复杂的也许就是参数的配置了,并且有许多参数都可以延伸出去讲很多,所以今天我们来看看dg的参数配置,顺便加上一点dataguard进程相关的信息,帮助理解. 在配置dg的过程中,我们 ...