You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Buildozer编译Kivy项目时遇Cython类型兼容错误求助

解决Kivy 2.2.1 + Buildozer 1.5.0编译Android时的SDL_RWops Cython错误

环境配置

  • Kivy 2.2.1
  • Buildozer 1.5.0
  • Python 3.0.2
  • 编译命令:buildozer android deploy

问题描述

执行编译命令时触发Cython编译错误,报错指向kivy/core/image/_img_sdl2.pyx文件,提示SDL_RWops的write函数指针异常类型不兼容,建议添加noexcept修饰符,但手动添加后问题仍未解决。

项目代码

from kivy.metrics import dp

from kivy.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.screen import MDScreen


class Example(MDApp):
    def build(self):
        years = [2017, 2018, 2019, 2020, 2021, 2022, 2023]

        self.data_tables = MDDataTable(
            # use_pagination= True,
            check=True,
            column_data=[("Год", dp(30))],
            row_data= [(str(year),) for year in years],
            sorted_on="Schedule",
            sorted_order="ASC",
            elevation=2)

        self.data_tables.bind(on_check_press=self.on_click_box)
        
        screen = MDScreen()
        screen.add_widget(self.data_tables)
        
        return screen

    def on_click_box(self, instance_table, current_row):
        print(current_row[0])


if __name__ == "__main__":
    app = Example()
    app.run()

错误代码段

报错位置的_img_sdl2.pyx代码:

cdef SDL_RWops *rwops_bridge_to_bytesio(byteio):
    # works only for write.
    cdef SDL_RWops *rwops = SDL_AllocRW()
    rwops.hidden.unknown.data1 = <void *>byteio
    rwops.seek = NULL
    rwops.read = NULL
    rwops.write = &rwops_bytesio_write
    rwops.close =&rwops_bytesio_close
    return rwops

解决方案

1. 升级核心依赖(优先推荐)

  • Python版本:Python 3.0.2过于老旧,Kivy 2.2.1官方推荐Python 3.7~3.11版本,升级到该区间内的稳定版本(比如3.9),老旧版本的C API与Cython的兼容性差,是导致类型不匹配的核心原因之一。
  • Buildozer版本:升级到最新稳定版(如1.5.1+),新版本修复了大量Android编译的依赖兼容问题。

2. 修正Cython函数的类型声明

若无法升级依赖,需同时修改函数定义和指针赋值:

  • 找到rwops_bytesio_write函数的定义,添加noexcept并确保签名与SDL的write函数完全匹配:
    cdecl int rwops_bytesio_write(SDL_RWops* context, const void* ptr, size_t size, size_t maxnum) noexcept
    
  • 在赋值write指针时,添加明确的类型强制转换:
    rwops.write = <int (*)(SDL_RWops*, const void*, size_t, size_t) noexcept>&rwops_bytesio_write
    

3. 指定兼容的SDL2版本

在buildozer.spec的[app]区块中添加以下配置,强制使用与Kivy 2.2.1兼容的SDL2版本:

android.ndk_sdl2_version = 2.26.5

4. 临时切换图像后端

若以上方法均无效,可临时禁用SDL2图像后端,改用PIL:
在项目入口文件(如main.py)的最顶部添加:

import os
os.environ['KIVY_IMAGE'] = 'pil,sdl2'

内容的提问来源于stack exchange,提问作者Oleg Palamarchuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:16:04