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就可以运行程序了。

相关推荐
mldong4 小时前
引擎从不发一条消息:jeeflow 的两类扩展点与消息模块的分工
java·架构
君顾15 小时前
智慧零售实战指南:从技术架构到落地方案全解析
java·开发语言·零售
南棱笑笑生5 小时前
20260904实测给飞凌OK3576-C开发板刷入Rockchip原厂的IMG固件【使用飞凌的DTS】切换串口波特率为1.5Mbps
c语言·开发语言·rockchip
zhanghe6875 小时前
es的密码带有特殊字符,导出
java
平头哥技术团队6 小时前
Day 10 | 工欲善其事:VS Code 配置与项目归档
android·开发语言·前端·javascript·html·交互
pnoker6 小时前
IoT DC3 概念解读:把设备抽象成一套语义模板——位号、指令、事件与面向智能体的设备建模
java·人工智能·物联网·iot·dc3
乌萨奇也要立志学C++6 小时前
【洛谷】kmp算法
开发语言·算法
my_realmy6 小时前
Java SE 基础学习笔记(一):面向对象、继承多态、抽象接口与异常(JDK 8)
java·多线程·并发··生产者消费者模式
传奇开心果编程6 小时前
【Rust入门知识点学与练】第4课:条件判断 if / else
开发语言·学习·rust
m0_380743876 小时前
给 Claude API 调用补上超时重试和错误分类
开发语言·人工智能·php