Lua调用C函数 – Qt实现
第一种方式:C函数作为应用程序的一部分,使用lua来调用
流程:
1.应用程序加载Lua脚本
2.Lua脚本中调用C函数中
程序:
luaCallC.pro
#-------------------------------------------------
#
# Project created by QtCreator 2019-12-18T14:24:19
#
#-------------------------------------------------
QT += core
QT -= gui
TARGET = luaCallC
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
HEADERS += \
lauxlib.h \
lua.h \
lua.hpp \
luaconf.h \
lualib.h
LIBS += -L$$PWD -llua53
main.cpp
#include <QCoreApplication>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>
using namespace std;
//待Lua调用的C注册函数。
static int add2(lua_State* L)
{
//检查栈中的参数是否合法,1表示Lua调用时的第一个参数(从左到右),依此类推。
//如果Lua代码在调用时传递的参数不为number,该函数将报错并终止程序的执行。
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
//将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。
lua_pushnumber(L,op1 + op2);
//返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。
return 1;
}
//另一个待Lua调用的C注册函数。
static int sub2(lua_State* L)
{
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
lua_pushnumber(L,op1 - op2);
return 1;
}
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
//将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为Lua代码
//在调用C函数时使用的全局函数名,第二个参数为实际C函数的指针。
lua_register(L, "add2", add2); //C函数作为应用程序的一部分
lua_register(L, "sub2", sub2);
//在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。
if(luaL_dofile(L,"base.lua")){
const char *error = lua_tostring(L, -1);
std::cout << error <<std::endl;
return false;
}
lua_close(L);
return 0;
}
require "mylib" --指定包名称
--在调用时,必须是package.function
print(mylib.add(1.0,2.0))
print(mylib.sub(20.1,19))
第二种方式:C函数作为动态链接库,使用lua来调用
流程:
1.使用QT生成共享库
2.lua调用dll,调用对应api
程序:
mylib.pro
#-------------------------------------------------
#
# Project created by QtCreator 2019-12-18T12:02:24
#
#-------------------------------------------------
QT -= core gui
TARGET = mylib
TEMPLATE = lib
DEFINES += MYLIB_LIBRARY
SOURCES += mylib.cpp
HEADERS += mylib.h \
lauxlib.h \
lua.h \
lua.hpp \
luaconf.h \
lualib.h
LIBS += -L$$PWD -llua53
unix {
target.path = /usr/lib
INSTALLS += target
}
DISTFILES += \
lua53.dll
mylib.h
#ifndef MYLIB_H
#define MYLIB_H
#if defined(MYLIB_LIBRARY)
# define MYLIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYLIBSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYLIB_H
mylib.cpp
#include "mylib.h"
#include <stdio.h>
#include <string.h>
#include <lua.hpp>
#include <lauxlib.h>
#include <lualib.h>
//待注册的C函数,该函数的声明形式在上面的例子中已经给出。
//需要说明的是,该函数必须以C的形式被导出,因此extern "C"是必须的。
//函数代码和上例相同,这里不再赘述。
extern "C" int add(lua_State* L)
{
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
lua_pushnumber(L,op1 + op2);
return 1;
}
extern "C" int sub(lua_State* L)
{
double op1 = luaL_checknumber(L,1);
double op2 = luaL_checknumber(L,2);
lua_pushnumber(L,op1 - op2);
return 1;
}
//luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字。
//第一个字段为C函数指针。
//结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。
static luaL_Reg mylibs[] = {
{"add", add},
{"sub", sub},
{NULL, NULL}
};
//该C库的唯一入口函数。其函数签名等同于上面的注册函数。见如下几点说明:
//1. 我们可以将该函数简单的理解为模块的工厂函数。
//2. 其函数名必须为luaopen_xxx,其中xxx表示library名称。Lua代码require "xxx"需要与之对应。
//3. 在luaL_register的调用中,其第一个字符串参数为模块名"xxx",第二个参数为待注册函数的数组。
//4. 需要强调的是,所有需要用到"xxx"的代码,不论C还是Lua,都必须保持一致,这是Lua的约定,
// 否则将无法调用。
extern "C" __declspec(dllexport)
int luaopen_mylib(lua_State* L)
{
luaL_newlib(L, mylibs); //c函数作为库供lua调用,使用luaL_newlib
return 1;
}
require "mylib" --指定包名称
--在调用时,必须是package.function
print(mylib.add(1.0,2.0))
print(mylib.sub(20.1,19))
评论(0)
您还未登录,请登录后发表或查看评论