关于love2d引擎require导入C/C++编写的.dll/.so扩展库问题

flaribbit · 更新于 2021-08-29 · 0 次阅读

源码

游戏项目中遇到的狗屎问题,分享一下解决经验,以一个最基本的程序为例:

test.c

c
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

static int about(lua_State *L){
    lua_pushstring(L,"test by flaribbit");
    return 1;
}

static const struct luaL_Reg funcList[]=
{
    {"about", about},
    {0, 0}
};

int luaopen_test(lua_State *L)
{
    luaL_register(L, "test", funcList);
    return 1;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

编译

windows 和 linux

在windows系统和linux系统中,可以直接使用gcc编译,注意链接lua51.dll或者libluajit.so,记得改掉下面命令中的path/to/

bash
gcc test.c path/to/lua51.dll -s -O2 -DNDEBUG -o test.dll
1
bash
gcc test.c path/to/libluajit.so -s -O2 -DNDEBUG -o libtest.so
1

然后在lua中调用require"test"就可以导入使用了,打包游戏的时候记得把库放在外面,和love.dll放在一起,不要塞进game.love或者exe

android系统就比较恶心了,自备NDK,以下教程写于windows系统,在test.c所在的目录创建Android.mkApplication.mk,下面的代码中记得修改path/to/,为liblove.so所在的目录(可以直接解压love2d的安装包拿)

安卓

Android.mk

makefile
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := test.c
LOCAL_LDFLAGS := -Lpath/to/$(TARGET_ARCH_ABI) -llove
LOCAL_C_INCLUDES := include
include $(BUILD_SHARED_LIBRARY)
1
2
3
4
5
6
7

Application.mk

makefile
APP_CPPFLAGS := -frtti 
APP_LDFLAGS := -latomic
APP_ABI := armeabi-v7a arm64-v8a
APP_PLATFORM := android-16
APP_OPTIM := release
1
2
3
4
5

然后调用ndk-build编译,日常记得修改path/to/

bash
path/to/ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk APP_BUILD_SCRIPT=Android.mk
1

会报可能错误链接的warning,问题不大,编译完成后会在libs文件夹里得到两个libtest.so

调用

最后编写lua程序,这里有个巨坑,*.so必须放到/data/data/package.name里面才能被require正确加载,否则会爆类似下面的神秘错误

txt
Error

error loading module 'test' from file '/sdcard/libtest.so':
dlopen failed: library "/sdcard/libtest.so" needed or dlopened by "/data/app/org.love2d.android.embed-cfg2TKQ-XsSj13FxWVvTUw==/lib/arm64/liblove.so" is not accessible for the namespace "classloader-namespace"

Traceback
[C]: at 0x7a3d813a7c
[C]: in function 'require'
/sdcard/prog.lua:2: in main chunk
[C]: in function 'require'
main.lua:2: in main chunk
[C]: in function 'require'
[C]: in function 'xpcall'
[C]: in function 'xpcall'
1
2
3
4
5
6
7
8
9
10
11
12
13
14

那么问题来了,如何放到/data/data/package.name里面呢…?

*.so文件打包进game.love,然后用下面的代码copy到save文件夹里,也算是个办法吧。

lua
package.cpath='/data/data/org.love2d.android.embed/files/save/archive/lib?.so;'..package.cpath
love.filesystem.write("libtest.so", love.filesystem.read("libtest.so"))
require "test"
1
2
3

it just works

github