美文网首页
2019-01-14

2019-01-14

作者: EPR | 来源:发表于2019-01-14 21:56 被阅读0次

Lua与C交互学习笔记

Lua与C交互是通过虚拟栈实现的

在C中调用Lua

方法一

--hello.lua
str = "Hello, Lua !"
table = {name = "cjj", id = 123456}
function myFunc(param1, param2)
    return value1,value2
end
#include <stdio.h>
#include "../include/lauxlib.h"

lua_State *load_lua(char *filename) {
    lua_State *L = luaL_newstate();//创建虚拟栈
    luaL_openlibs(L);//打开lua文件

    //加载脚本并运行
    if (luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) {
        printf("load Lua script failed: %s\n", lua_tostring(L, -1));
        return NULL;
    }

    return L;
}

int main(int argc, const char *argv[]) {

    char* lua_filename = ".\\hello.lua";//.lua路径
    lua_State *L = load_lua(lua_filename);//加载lua文件
    if (NULL == L) {
        return -1;
    }

    //读取变量
    lua_getglobal(L, "str");//将str变量压入栈顶
    printf("%s\n", lua_tostring(L, -1));

    //读取table
    lua_getglobal(L, "table");//将table压入栈顶
    lua_getfield(L, -1, "name");//将索引-1对应的table中的name变量压入栈顶
    printf("%s\n", lua_tostring(L, -1));

    //调用函数
    lua_getglobal(L, "myFunc"); //读取函数到栈顶
    lua_pushnumber(L, param1); //压入参数
    lua_pushnumber(L, param2);
    //参数依次为虚拟栈,压入参数数,返回值数,错误回调函数(为0时将错误信息压入栈顶)
    //调用函数成功会弹出参数与函数并压入返回值
    if (lua_pcall(L, 2, 2, 0) != 0) {
        printf("lua_pcall failed: %s\n", lua_tostring(L, -1));
        return -1;
    }
    int value2 = lua_tonumber(L, -1);
    printf("%d\n", value2);
    int value1 = lua_tonumber(L, -2);
    printf("%d\n", value1);

    lua_close(L);
    return 0;
}

栈中的情况如下表所示

索引 类型
5 (var) value2
4 (var) value1
3 string cjj
2 table table
1 string Hello, Lua !

方法二

#include <stdio.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
/* 指向Lua解释器的指针 */
lua_State* L;
static int myFunc(lua_State *L)
{
    
    /* 返回返回值的个数 */
    return n;
}

int main(int argc, char *argv[])
{
    /* 初始化Lua */
    L = lua_open();
    /* 载入Lua基本库 */
    luaL_openlibs(L);
    /* 注册函数 */
    lua_register(L, "myFunc", myFunc);
    /* 运行脚本 */
    luaL_dofile(L, "test.lua");
    /* 清除Lua */
    lua_close(L);
    return 0;
}

--test.lua
value1,value2... = myFunc(param1,param2...)

在Lua中调用C

Lua通过调用动态库(.dll)方法调用C

创建动态库

以VS2017为例


创建.dll项目
//mylualib.h
#pragma once
//加入lua库
#include "..\include\lua.h"  
#include "..\include\lualib.h"  
#include "..\include\lauxlib.h"  

__declspec(dllexport) int luaopen_myLualib(lua_State *L);//定义导出函数
//myLualib.c
#include <stdio.h>  
#include "myLualib.h"  

static int myFunc1(lua_State *L)
{  
   /*****************************************
    常用的函数
    lua_gettop(L)得到参数个数
    lua_tonumber(L, 1)获取数值型参数param1
    lua_tonumber(L, 2)获取数值型参数param2
    ...
    lua_pushnumber(L, value1)返回值value1
    lua_pushnumber(L, value2)返回值value2
    ...
    ****************************************/
    //函数体
    return n;     //返回值个数  
}

static int myFunc2(lua_State* L)
{
    return n;
}

static const struct luaL_Reg myLib[] =
{
    {"myFunc1", myFunc1},
    {"myFunc2", myFunc2},
    {NULL, NULL}       //数组中最后一对必须是{NULL, NULL},用来表示结束      
};

int luaopen_myLualib(lua_State *L)
{
    luaL_register(L, "moduleName", myLib);
    return 1;       // 把myLib表压入了栈中,所以就需要返回1  
}

Lua中加载.dll

dllPath=".\\Dll1.dll"--.dll路径
outFuncName="luaopen_mLualib"--导出函数名
local testlib = package.loadlib(dllPath,outFuncName);
if(testlib)then
    testlib();  --打开模块
    value1,value2... = moduleName.myFunc1(param1,param2...) -- 参数对应堆栈中的数据
    moduleName.myFunc2()   --调用myFunc2()
else
    print("error")-- Error
end

相关API

Lua 5.1 Reference Manual

相关文章

网友评论

      本文标题:2019-01-14

      本文链接:https://www.haomeiwen.com/subject/tenjdqtx.html