android studio编译SDL so库

一、下载源码

SDL官网
在这里插入图片描述
在这里插入图片描述

二、解压,拷贝android项目,并重新命名

2.1、解压

在这里插入图片描述

2.2,重命名项目名称(androidSDL)AndroidSDL Github

在这里插入图片描述

三、导入头文件和源文件,修改android.mk文件

3.1、在jni目录下创建SDL2文件夹,并拷贝相关头文件和源文件到该目录下

在这里插入图片描述

3.2、在jni/src目录下创建.cpp文件

在这里插入图片描述
main.cpp

#include "SDL.h"
int main(int,char**){
   return 0;
}

3.3、修改jni/src下的android.mk文件

在这里插入图片描述
Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := main

SDL_PATH := ../SDL2

LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include

# Add your application source files here...
LOCAL_SRC_FILES := main.cpp

LOCAL_SHARED_LIBRARIES := SDL2

LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid

include $(BUILD_SHARED_LIBRARY)

四、使用NDK编译

4.1、环境变量path配置ndk路径

在这里插入图片描述

4.2、打开cmd命令窗口,进入到androidSDL/app/jni/目录,然后执行"ndk-build"命令进行编译

在这里插入图片描述

4.3、根目录下生成libs目录,里面会有对应的so库

在这里插入图片描述
在这里插入图片描述

五、依赖so库

5.1、创建新项目(AndroidSDLThread)Github

在这里插入图片描述

5.2、src/main创建jniLibs目录,拷贝so库

在这里插入图片描述

5.3、src/main/cpp下创建include文件夹,拷贝SDL头文件至此

在这里插入图片描述

5.4、CMakeList.txt文件下配置SDL头文件和库文件

cmake_minimum_required(VERSION 3.18.1)
project("androidsdlthread")

#SDL统一路径
set(sdl_path ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
#添加SDL头文件
include_directories(${CMAKE_SOURCE_DIR}/include/SDL)
#添加SDL库
add_library(sdl SHARED IMPORTED)
set_target_properties(sdl PROPERTIES IMPORTED_LOCATION ${sdl_path}/libSDL2.so)

add_library(sdl_shared SHARED IMPORTED)
set_target_properties(sdl_shared PROPERTIES IMPORTED_LOCATION ${sdl_path}/libc++_shared.so)

add_library(sdl_main SHARED IMPORTED)
set_target_properties(sdl_main PROPERTIES IMPORTED_LOCATION ${sdl_path}/libmain.so)

add_library(
        androidsdlthread
        SHARED
        native-lib.cpp
        ${CMAKE_SOURCE_DIR}/logger.h)
find_library(
        log-lib
        log)
target_link_libraries( # Specifies the target library.
        androidsdlthread
        sdl
        sdl_shared
        sdl_main
        -landroid
        ${log-lib})

在这里插入图片描述

六、使用SDL信号量,实现等待通知机制

SDL(Simple DirectMedia Layer)库提供了信号量(semaphore)的支持,用于实现线程间的同步和通信。信号量是一种计数器,用于控制对共享资源的访问,可以实现多线程之间的同步和互斥,确保线程安全和资源的正确访问。

  • 创建信号量:调用SDL_CreateSemaphore() 函数创建一个信号量对象。在底层,SDL库会调用操作系统提供的原生信号量创建函数,如sem_init()(Linux)或CreateSemaphore()(Windows)。
  • 等待信号量:调用SDL_SemWait() 或类似的函数等待信号量。在底层,SDL库会调用操作系统提供的原生信号量等待函数,如sem_wait()(Linux)或WaitForSingleObject()(Windows)。如果信号量的计数值大于0,则将计数值减1,线程可以继续执行。如果计数值为0,则线程会被阻塞,直到有其他线程调用SDL_SemPost()增加了信号量的计数值。
  • 发送通知:调用SDL_SemPost() 函数增加信号量的计数值。在底层,SDL库会调用操作系统提供的原生信号量增加函数,如sem_post()(Linux)或ReleaseSemaphore()(Windows)。增加计数值后,如果有线程正在等待该信号量其中一个线程将被唤醒,可以继续执行。
  • 销毁信号量:调用SDL_DestroySemaphore() 函数销毁信号量对象。在底层,SDL库会调用操作系统提供的原生信号量销毁函数,如sem_destroy()(Linux)或CloseHandle()(Windows)。

6.1、声明native方法

    public native void startSDLThread();

    public native void postSDL();

    public native void releaseSDL();

6.2、生成jni函数

#include <jni.h>
#include <string>

extern "C" {
#include <SDL_thread.h>
#include "logger.h"

SDL_sem *g_sem = NULL;
int g_task_exit = 0;
int task1(void *data);
int task2(void *data);
int number=0;

JNIEXPORT void JNICALL
Java_com_anniljing_androidsdlthread_MainActivity_startSDLThread(JNIEnv *env, jobject thiz) {
    g_task_exit=0;
    g_sem = SDL_CreateSemaphore(0);
    SDL_CreateThread(task1, "task1", NULL);
    SDL_CreateThread(task2, "task2", NULL);
}
JNIEXPORT void JNICALL
Java_com_anniljing_androidsdlthread_MainActivity_postSDL(JNIEnv *env, jobject thiz) {
    if (g_sem) {
        SDL_SemPost(g_sem);
    }
}

JNIEXPORT void JNICALL
Java_com_anniljing_androidsdlthread_MainActivity_releaseSDL(JNIEnv *env, jobject thiz) {
    g_task_exit = 1;
    SDL_DestroySemaphore(g_sem);
    g_sem = NULL;
}
int task1(void *data) {
    while (!g_task_exit) {
        if (g_sem) {
            LOGD("task1 SemWait");
            SDL_SemWait(g_sem);
            number++;
            LOGD("task1 number:%d\n",number);
        }
    }
    return 0;
}
int task2(void *data) {
    while (!g_task_exit) {
        if (g_sem) {
            LOGD("task2 SemWait");
            SDL_SemWait(g_sem);
            number++;
            LOGD("task2 number:%d\n",number);
        }
    }
    return 0;
}
}


6.3、编译运行

在这里插入图片描述
在这里插入图片描述
我们需要把这个文件夹拷贝到自己的项目
在这里插入图片描述
在这里插入图片描述

  • 启动了两个线程
  • 虽然线程2被唤起的次数多一些,但是当线程1执行的时候,变量number也是同步的
### 如何在Android Studio中添加或配置SDL #### 配置项目结构 为了使SDL能够在Android Studio环境中正常工作,需要调整项目的整体架构。确保拥有一个支持C/C++的项目设置,在创建新项目时勾选`Include C++ support`选项[^1]。 #### 设置Gradle版本 由于使用的是较新的Android Studio版本(如3.0),因此需确认使用的最低Gradle版本不低于4.1以兼容最新的构建工具特性[^2]。 ```gradle buildscript { repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:7.0.2' // 或者更高版本 } } ``` #### 添加JNI文件夹并导入SDL源码 在工程中的`app/src/main/cpp/jni/`路径下建立名为`SDL`的新文件夹,并将SDL官方发布的源代码包内的`include`, `src`以及`Android.mk`复制至此处[^4]。 #### 修改`CMakeLists.txt` 对于采用CMake作为外部原生构建系统的项目而言,编辑位于模块根目录下的`CMakeLists.txt`来指定SDL头文件位置及其预编译二进制链接: ```cmake set(SDL_PATH ${CMAKE_SOURCE_DIR}/../SDL) add_library( sdl STATIC IMPORTED ) set_target_properties(sdl PROPERTIES IMPORTED_LOCATION ${SDL_PATH}/lib/${ANDROID_ABI}/libSDL2.a) include_directories(${SDL_PATH}/include/) ``` #### 更新`build.gradle (Module)` 最后一步是在应用级别的`build.gradle`里声明对外部依赖项的支持,特别是针对NDK部分做适当修改以便于识别自定义的`.mk`脚本和关联静态: ```groovy android { ... defaultConfig { ... externalNativeBuild { cmake { cppFlags "-std=c++11" arguments '-DANDROID_STL=c++_shared' } } ndk { abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64" } } externalNativeBuild { cmake { path "CMakeLists.txt" } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':openFrameworks')// 如果有其他子项目的话 } ``` 通过上述操作可以有效地解决Android Studio环境下缺失SDL的问题,使得开发者能够顺利地基于此框架开展多媒体应用程序的研发工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值