Skip to content

C动态链接库加载

Smile Yik edited this page Oct 23, 2022 · 3 revisions

最后更新于2022年10月23日 | 历史记录

此页面内容对应于LuaInMinecraftBukkit插件的最新版本(及以上版本)(version: 1.7.1), 历史文档可以插件此页面的历史记录

前言

LuaInMinecraftBukkit在Native模式中所加载的动态链接库都是x64位的, 所以要制作的拓展库也应该 编译成x64位!

目前LuaInMinecraftBukkit以Native模式运行时有两个版本的LuaVM可供选择, 一种为lua5.4版本, 而另一种为lua5.1(luajit2.1.0_beta3)版本, 在制作拓展库时, 需要注意到luaL_newlib 方法对于两种版本来说并不是通用的, 此方法仅在lua5.4版本中生效

本文将以LuaInMinecraftBukkit默认选择的lua5.4版本为主介绍如何在脚本中使用C动态链接库

环境准备

windows

暂时没有

linux

LuaInMinecraftBukkit.jar(压缩包打开)中的libs/lua5.4/linux/liblua.so文件
lua5.4.4源代码(官网获取)

制作拓展库

这里以制作一个简单的打印Hello, world!句子的拓展库为例子.

windows

暂时没有

linux

以下操作不唯一, 仅当参考, 可以按照个人喜好来

  1. 在任意目录下创建一个名为 lualib 目录
  2. 将lua5.4.4源代码解压到 lualib 目录中
  3. 复制LuaInMinecraftBukkit.jar(压缩包打开)中的libs/lua5.4/linux/liblua.so文件 到 lualib 目录中
  4. 当前目录看起来是这个样子, 并且进入 lualib 目录
❯ tree lualib
lualib
├── liblua.so
└── lua-5.4.4
    ├── doc
    │   └── ...
    ├── Makefile
    ├── README
    └── src
        ├── lapi.c
        ├── lapi.h
        ├── lauxlib.c
        ├── lauxlib.h
        └── ...

3 directories, 76 files
  1. 创建一个名为 lualib.c 文件, 在里面填写入如下内容
#include <stdio.h>
#include "lua-5.4.4/src/lua.h"
#include "lua-5.4.4/src/lualib.h"
#include "lua-5.4.4/src/lauxlib.h"

/********************************************
 *
 * 这里是3个最简单的函数,
 * 第一个形参得是 lua_State* 类型
 * 函数返回值得是 int 类型
 *
 *************************************************
 */

int hello_world(lua_State* L) {
  printf("Hello, world!");
  return 1;
}

int hello_lua(lua_State* L) {
  printf("Hello, lua!\n");
  return 1;
}

int hello_c(lua_State* L) {
  printf("Hello, c!\n");
  return 1;
}

/********************************************
 *
 * lua加载动态库入口
 * 格式为 luaopen_拓展库名
 *
 * 当在lua中使用 require("a") 时,
 * 如果找到了a.so,
 * 则会执行里面的 luaopen_a(lua_State*) 方法
 *
 *************************************************
 */
int luaopen_lualib(lua_State* L) {
  /**********************
   * 构建一张方法表
   *
   * 最后要以NULL:NULL结尾
   * ********************
   */
  const struct luaL_Reg my_funs[] = {
    {"hello_world", hello_world},
    {"hello_lua", hello_lua},
    {"hello_c", hello_c},
    {NULL, NULL}
  };

  luaL_newlib(L, my_funs);
  return 1;
}
  1. 在当前目录下打开终端, 输入如下指令对lualib.c进行编译
gcc -shared -fPIC lualib.c -L$PWD -llua -o lualib.so

至此, 拓展库编译完成

创建一个lua插件

  1. plugins/LuaInMinecraftBukkit/plugins文件夹下, 创建一个名为clibtest 文件夹, 进入该文件夹
  2. 创建lua_plugin.yml文件在clibtest文件夹下, 并填入以下信息, 向插件注册该 lua插件
# 展示用的名字
displayName: clibtest
# 脚本插件id, 建议插件id与目录名保持一致, 并且只使用26个英文字母组成
id: clibtest
# 作者
author: SmileYik
# 脚本版本
version: 1.0
# 强制依赖插件, 是一个列表
# 其中列表里是其他依赖脚本插件的脚本插件id
dependents: []
# 非强制依赖插件, 是一个列表
# 其中列表里是其他依赖脚本插件的脚本插件id
softDependents: []
mode: Outside
  1. 创建main.lua文件, 在其中写入如下文本
local mylib = require("lualib")

-- 当脚本插件被启用时会执行这个方法
function onEnable()
    mylib.hello_world()
    mylib.hello_lua()
    mylib.hello_c()
    print("加载完毕")
end

-- 当脚本插件被结束时会执行这个方法
function onDisable()
    print("卸载完毕")
end
  1. clibtest文件夹下创建一个c_libraries文件夹, 并且将之前编译好的"lualib.so" 文件复制到c_libraries文件夹中
  2. 启动服务器后看见如下效果
[15:54:06] [Server thread/INFO]: [LuaInMinecraftBukkit] 版本已加载: LUA_5_4
[15:54:06] [Server thread/INFO]: [LuaInMinecraftBukkit] 正在启用混合模式.....
[15:54:06] [Server thread/INFO]: [LuaInMinecraftBukkit] 正在加载插件: clibtest(clibtest), 作者: SmileYik, 版本: 1.0
>Hello, world!Hello, lua!
Hello, c!
加载完毕[15:54:06] [Server thread/INFO]: [LuaInMinecraftBukkit] 正在以Native模式启用插件: clibtest(clibtest), 作者: SmileYik, 版本: 1.0
[15:54:06] [Server thread/INFO]: Server permissions file permissions.yml is empty, ignoring it
[15:54:06] [Server thread/INFO]: Done (7.241s)! For help, type "help"