lua库之注册C语言函数
问题情景:
日前,项目中遇到一个问题,需要将数据包中的ssid进行gb2312编码后发送出去。但设备所用的lua版本未移植luaiconv库。
但C语言中已有转码的库 libiconv.so ,转码函数为 iconv_string() (这是我们自己将C语言iconv函数族进行了封装而成的) ,因此想到通过lua调用c函数,就不必再移植luaiconv库了。
那么,如何在lua中调用c函数?
解决方法
1. 定义头文件 register.h
头文件中extern 声明引用iconv_string函数,否则注册写完了也找不到这个函数
注意要包含这几个lua的头文件,注册lua函数需要用到
#ifndef __REGISTER_H__
#define __REGISTER_H__
#include<stdio.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
extern char *iconv_string (const char *str, const char *from_codeset,const char *to_codeset);
#endif
2. 定义注册文件 register.c
在此文件中将C函数注册为lua函数,根据需要去找注册需要的lua接口
#include "register.h"
/* 所有注册给Lua的C函数具有
* "typedef int (*lua_CFunction) (lua_State *L);"的原型。
*/
static int luaiconv(lua_State *L)
{
// 从虚拟栈中获取所需的三个参数
// luaL_checkstring() 如果给定虚拟栈中索引处的元素可以转换为字符串,则返回转换后的字符串,否则报错。
char *str= (char*) luaL_checkstring(L, 1);
char *from_codeset= (char*) luaL_checkstring(L, 2);
char *to_codeset= (char*) luaL_checkstring(L, 3);
char *result = NULL;
/* 调用 C中的函数 */
result = iconv_string(str,from_codeset,to_codeset);
if(!result){
lua_pushstring(L, str);
return 1;
}
lua_pop(L,3); // 弹出栈顶3个元素
/* C可以返回给Lua多个结果,
* 通过多次调用lua_push*(),之后return返回结果的数量。
* 这里返回一个字符串
*/
lua_pushstring(L, result);
free(result);
return 1; /* 结果的数量 */
}
/* 需要一个"luaL_Reg"类型的结构体,其中每一个元素对应一个提供给Lua的函数。
* 每一个元素中包含此函数在Lua中的名字,以及该函数在C库中的函数指针。
* 最后一个元素为“哨兵元素”(两个"NULL"),用于告诉Lua没有其他的函数需要注册。
*/
static luaL_Reg mylibs[] = {
{"luaiconv", luaiconv},
{NULL,NULL}
};
/* 此函数为C库中的“特殊函数”。
* 通过调用它注册所有C库中的函数,并将它们存储在适当的位置。
* 此函数的命名规则应遵循:
* 1、使用"luaopen_"作为前缀。
* 2、前缀之后的名字将作为"require"的参数。
*/
int luaopen_libmqttlua(lua_State* L)
{
/*以下内容也可以用其他接口实现*/
lua_newtable(L);
luaL_setfuncs(L,mylibs,0);
return 1;
}
3. 编译
最后,将register.c编译成动态库,要注意的是,因为iconv_string函数在libiconv.so库中,千万别忘了链接这个库
在Makefile中添加链接库所在路径和链接库-L$(ROOTDIR)/lib/lib -liconv
即可
参考博客http://blog.csdn.net/vermilliontear/article/details/50947379