Java使用FFM API调用SDL

首发于Enaium的个人博客


首先我们需要创建一个Gradle项目,之后设置项目的JDK版本,设置为22及以上版本。

kotlin 复制代码
plugins {
    kotlin("jvm") version "2.1.0"
}

group = "cn.enaium"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    testImplementation(kotlin("test"))
}

tasks.test {
    useJUnitPlatform()
}
kotlin {
    jvmToolchain(23)
}

接着我们在当前目录初始化git仓库,之后需要添加一个子模块。、

复制代码
git init
git submodule add git@github.com:libsdl-org/SDL.git SDL

之后编写生成接口的脚本,在这之前你必须安装CMakejextract到环境变量中。

powershell 复制代码
$sdl_path = "SDL"
mkdir "$sdl_path/build"; cmake -DCMAKE_BUILD_TYPE=Release "$sdl_path" -B "$sdl_path/build"; cmake --build "$sdl_path/build" --config Release --parallel
jextract --include-dir "$sdl_path/include" --dump-includes "$sdl_path/build/includes.txt" "$sdl_path/include/SDL3/SDL.h"
jextract --include-dir "$sdl_path/include" --output src/main/java --target-package org.libsdl --library SDL3 --use-system-load-library "@$sdl_path/build/includes.txt" "$sdl_path/include/SDL3/SDL.h"

首先是使用CMake编译SDL,之后使用jextract生成Java接口,之后运行脚本,这样就会在src/main/java生成SDL3的接口。

接着我们回到build.gradle.kts,添加application插件,之后将编译好的路径添加到启动参数中。

kotlin 复制代码
plugins {
    application
}

application {
    mainClass = "MainKt"
    applicationDefaultJvmArgs = listOf("-Djava.library.path=SDL/build/Release", "--enable-native-access=ALL-UNNAMED")
}

之后就可以调用SDL的接口了。

kotlin 复制代码
import org.libsdl.*
import org.libsdl.SDL_h_1.*
import java.lang.foreign.Arena

/**
 * @author Enaium
 */
fun main() {
    Arena.ofConfined().use {
        val init = SDL_h_2.SDL_Init(SDL_INIT_VIDEO() and SDL_INIT_EVENTS())

        if (!init) {
            println("SDL_Init Error: ${SDL_h_3.SDL_GetError()}")
            return
        }

        val windowPtr = it.allocate(C_POINTER)
        val rendererPtr = it.allocate(C_POINTER)

        SDL_CreateWindowAndRenderer(it.allocateFrom("Hello World"), 640, 480, 0, windowPtr, rendererPtr)

        val window = windowPtr.get(C_POINTER, 0)
        val renderer = rendererPtr.get(C_POINTER, 0)

        val rect = SDL_FRect.allocate(it)
        SDL_FRect.x(rect, 100f)
        SDL_FRect.y(rect, 100f)
        SDL_FRect.w(rect, 440f)
        SDL_FRect.h(rect, 280f)


        val event = SDL_Event.allocate(it)
        var quit = false
        while (!quit) {
            while (SDL_PollEvent(event)) {
                when (SDL_Event.type(event)) {
                    SDL_EVENT_QUIT() -> {
                        quit = true
                    }

                    SDL_EVENT_KEY_DOWN() -> {
                        when (SDL_KeyboardEvent.key(SDL_Event.key(event))) {
                            SDLK_UP() -> {
                                SDL_FRect.y(rect, SDL_FRect.y(rect) - 5)
                            }

                            SDLK_DOWN() -> {
                                SDL_FRect.y(rect, SDL_FRect.y(rect) + 5)
                            }

                            SDLK_LEFT() -> {
                                SDL_FRect.x(rect, SDL_FRect.x(rect) - 5)
                            }

                            SDLK_RIGHT() -> {
                                SDL_FRect.x(rect, SDL_FRect.x(rect) + 5)
                            }
                        }
                    }
                }
            }

            SDL_h_2.SDL_SetRenderDrawColor(renderer, 33.toByte(), 33.toByte(), 33.toByte(), 255.toByte())
            SDL_h_2.SDL_RenderClear(renderer)

            SDL_h_2.SDL_SetRenderDrawColor(renderer, 0.toByte(), 0.toByte(), 255.toByte(), 255.toByte())

            SDL_h_2.SDL_RenderFillRect(renderer, rect)

            SDL_h_2.SDL_RenderPresent(renderer)
        }

        SDL_h_2.SDL_DestroyRenderer(renderer)
        SDL_h_3.SDL_DestroyWindow(window)
    }
}

首先这里创建了一个窗口和渲染器,还渲染了一个矩形。之后做了事件处理,关闭的时候跳出循环,之后销毁窗口和渲染器。按下键盘上下左右键可以移动矩形。

之后调用./gradlew run就可以运行程序了。

相关推荐
宠..13 小时前
QPlainText方法大全
开发语言·qt
Mr-Wanter13 小时前
搭建局域网时间同步服务器
java·运维·服务器
代码笔耕13 小时前
我们这样设计消息中心,解决了业务反复折腾的顽疾
java·后端·架构
Chukai12313 小时前
第3章:基于LlamaIndex+Ollama+ChromaDB搭建本地简单RAG问答系统
开发语言·人工智能·python·rag·rag问答系统
代码游侠13 小时前
应用——UDP 网络编程
linux·运维·开发语言·学习·算法
私人珍藏库13 小时前
[吾爱大神原创工具] PythonEnvManager - Python 环境管理工具 [更新自定义扫描路径]
开发语言·python
没有bug.的程序员13 小时前
负载均衡的真正含义:从算法到架构的深度解析
java·jvm·算法·微服务·架构·负载均衡
yc_xym13 小时前
[项目实践]言聚论坛(后端)
java·项目开发
唐装鼠13 小时前
Rust Turbofish 语法详解(deepseek)
开发语言·后端·rust
多仔ヾ13 小时前
Solon + EasyQuery + ElementPlus 实现后台管理系统之 08-权限认证优化
java