【问题标题】:dlopen failed(return NULL) when add SDL2 to android project将 SDL2 添加到 android 项目时 dlopen 失败(返回 NULL)
【发布时间】:2019-04-23 03:44:06
【问题描述】:

我在 Android Studio3.4 上使用 cmake3.6(NDK19)SDL2.0.9 添加到我的 Android 项目中,但出现此错误:

" E/SDL: nativeRunMain(): Couldn't load library /data/app/org.libsdl.app-eOed871MljqNS6cZDl_DBg==/lib/arm64/libmain.so"

调试后发现SDL2/src/core/androd/SDL_android.c中有这行(library_handle is NULL):

library_handle = dlopen(library_file, RTLD_GLOBAL);
if (library_handle) {
...
} else {
        __android_log_print(ANDROID_LOG_ERROR, "SDL", "nativeRunMain(): Couldn't load library %s", library_file);
}

下面是我的CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)

file(GLOB my_source ${CMAKE_SOURCE_DIR}/*.cpp ${CMAKE_SOURCE_DIR}/*.c)

add_library(main
        SHARED
        main.cpp)

include_directories(${CMAKE_SOURCE_DIR}/include)

add_subdirectory(${CMAKE_SOURCE_DIR}/SDL2)
include_directories(${CMAKE_SOURCE_DIR}/SDL2/include)

find_library(log-lib
        log)

target_link_libraries(
        main
        SDL2
        GLESv1_CM
        GLESv2
        -landroid
        ${log-lib})

还有我的ma​​in.cpp

#include <android/log.h>

#define LOG_TAG "gmyffplay"
#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))

#include "SDL.h"

extern "C" {

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

    char *video_path = argv[1];
    LOGI("video_path  : %s", video_path);

    SDL_Window *window;
    SDL_Renderer *renderer;
    SDL_Event event;

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        LOGE("Could not initialize SDL - %s", SDL_GetError());
        return 1;
    }

    window = SDL_CreateWindow("SDL_Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 0, 0,
                              SDL_WINDOW_SHOWN);
    renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Surface *bmp = SDL_LoadBMP("image.bmp");
    SDL_SetColorKey(bmp, SDL_TRUE, 0xffffff);
    SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, bmp);
    SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
    while (1) {
        if (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                break;
            }
        }
        SDL_SetRenderDrawColor(renderer, 0, 133, 119, 255);
        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);
    }
    SDL_FreeSurface(bmp);
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}
}

我确定 library_file 存在,apk 中的 libmain.so 和 libSDL2 在 libmain.so 之前加载。

任何帮助我的人将不胜感激

编辑:

这是我的项目架构

【问题讨论】:

  • 在我将 AndroidStudio 升级到 3.4 版(以及 gragle 到 5.1.1、ndk 19c、android gradle 插件 3.4)后,我开始遇到同样的问题所以我必须尝试恢复到 AndroidStudio 3.3.2、ndk19b,毕业 4.10.3)
  • 在最新的 AndroidStudio Canary 上使用最新的 gradle(5.4) 插件同样的问题
  • 最后,我使用了ndk-build intead,效果很好

标签: android cmake sdl


【解决方案1】:

我在android-ndk github issues 上找到了一个解决方案,似乎在查找用于动态链接 libdl.so 库的库时出现问题,其中声明了 dlopen 函数。

所以你需要在 SDL2/CMakeLists.txt 中将find_library(ANDROID_DL_LIBRARY dl) 更改为
find_library(ANDROID_DL_LIBRARY NAMES libdl.so dl)

【讨论】:

  • 这仅对 armeabi-v7a 有效,但对 arm64-v8a 无效。尝试使用 NDK20b
【解决方案2】:

目前我只找到了一种解决方案:将 NDK 降级到 r18b(r19c - 不起作用)。和dlopen 开始加载库。我无法找出究竟发生了什么课程dlerror 总是返回(null),无论我尝试从其他共享库加载共享库。你可以在这里找到旧的 ndk 版本:https://developer.android.com/ndk/downloads/older_releases.html 下载并解压,然后添加到你的 local.properties 文件中:

ndk.dir=/home/<your_path>/android-ndk-r18b

更新: 新的 NDK 有 dlopen 和其他 C 函数的存根,以前的 NDK 直接实现它,现在你必须选择最小目标到 21 或使用旧的 NDK

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    相关资源
    最近更新 更多