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

使用rust-cpython开发Android库,交叉编译后遇PyModule_Type等符号缺失错误

Android Kivy应用调用Rust扩展库时符号缺失问题

问题描述

我正在开发一款Android应用,基于Python的Kivy框架开发并使用Buildozer构建,同时开发了基于Rust的扩展库,通过cpython crate实现。从Linux x86_64平台交叉编译到aarch64-linux-android目标时,执行cargo build --target aarch64-linux-android可完成编译,但在手机上运行应用时出现以下错误:

  • 未添加--release标签编译时:
Traceback (most recent call last):
File "/home/feluk6174/python/lib_test/.buildozer/android/app/main.py", line 26, in <module>
ImportError: dlopen failed: cannot locate symbol "PyModule_Type" referenced by "/data/data/org.test.doxa_test/files/app/doxa_api.so"
  • 添加--release标签编译时:
Traceback (most recent call last):
File "/home/feluk6174/python/lib_test/.buildozer/android/app/main.py", line 26, in <module>
ImportError: dlopen failed: cannot locate symbol "PyExc_OverflowError" referenced by "/data/data/org.test.doxa_test/files/app/doxa_api.so"

环境说明

参考Mozilla的Rust on Android教程配置了Rust和NDK,之前曾遇到ld: error: unable to find library -lgcc错误,采用GitHub上的修复方案解决后可完成编译,但出现上述符号缺失问题。

相关代码

Rust库代码(lib.rs)

#[macro_use]
extern crate cpython;

use cpython::{Python, PyResult};


py_module_initializer!(doxa_api, doxa_api, PyInit_doxa_api, |py, m | {
    m.add(py, "__doc__", "This module is implemented in Rust")?;
    m.add(py, "test", py_fn!(py, 
        test(a: u8, b:u8) -> PyResult<u8>{
            Ok(a as u8+b as u8)

        }
    ))?;
    Ok(())
});

Cargo.toml配置

[package]
name = "doxa_api"
version = "0.1.0"
edition = "2021"


[lib]
name = "doxa_api"
crate-type = ["cdylib"]

[dependencies]
cpython = {version = "*",  features = ["extension-module"]}

.cargo/config.toml配置

[target.aarch64-linux-android]
ar = "/home/feluk6174/rust/doxa_api/NDK/arm64/bin/aarch64-linux-android-ar"
linker = "/home/feluk6174/rust/doxa_api/NDK/arm64/bin/aarch64-linux-android-clang"

[target.armv7-linux-androideabi]
ar = "/home/feluk6174/rust/doxa_api/NDK/arm/bin/arm-linux-androideabi-ar"
linker = "/home/feluk6174/rust/doxa_api/NDK/arm/bin/arm-linux-androideabi-clang"

[target.i686-linux-android]
ar = "/home/feluk6174/rust/doxa_api/NDK/x86/bin/i686-linux-android-ar"
linker = "/home/feluk6174/rust/doxa_api/NDK/x86/bin/i686-linux-android-clang"

Python应用代码(main.py)

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager
import kivy.uix.screenmanager
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout

import random

import doxa_api

class TestApp(App):

    def build(self):
        sm = ScreenManager()

        sm.add_widget(Screen(name = "screen"))
        
        return sm

class Screen(kivy.uix.screenmanager.Screen):
    def __init__(self, **kwargs):
        super(Screen, self).__init__(**kwargs)
        self.main_box = BoxLayout(orientation = "vertical")
        self.add_widget(self.main_box)

        self.button = Button(text = "try", on_release = self.test)
        self.main_box.add_widget(self.button)


    def test(self, t):
        print("a")
        
        self.button.text = str(doxa_api.test(1, random.randint(0,254)))
        
        

if __name__ == '__main__':
    TestApp().run()

版本信息

Python 3.10.9、Kivy 2.1.0、Buildozer 1.5.0、Rust 1.67.0


解决方案

核心原因

Rust扩展库编译时未链接到Buildozer打包的Android Python运行时对应的Python库,导致运行时无法找到Python内部符号。

具体修复步骤

  1. 定位Buildozer的Android Python库路径
    Buildozer构建时会下载对应架构的Python库,路径通常为:.buildozer/android/platform/python-for-android/build/other_builds/python3/<arch>/android_<arch>/usr/lib/,例如aarch64架构的路径是.buildozer/android/platform/python-for-android/build/other_builds/python3/arm64-v8a/android_arm64_v8a/usr/lib/,找到对应版本的libpython3.10.so文件。

  2. 修改Rust交叉编译的链接参数
    在.cargo/config.toml中为每个Android目标添加rustflags,指定链接到Python库:

    [target.aarch64-linux-android]
    ar = "/home/feluk6174/rust/doxa_api/NDK/arm64/bin/aarch64-linux-android-ar"
    linker = "/home/feluk6174/rust/doxa_api/NDK/arm64/bin/aarch64-linux-android-clang"
    rustflags = [
        "-C", "link-arg=-L/实际路径/buildozer/python/lib",
        "-C", "link-arg=-lpython3.10",
        "-C", "link-arg=-Wl,-rpath=$ORIGIN"
    ]
    
    [target.armv7-linux-androideabi]
    ar = "/home/feluk6174/rust/doxa_api/NDK/arm/bin/arm-linux-androideabi-ar"
    linker = "/home/feluk6174/rust/doxa_api/NDK/arm/bin/arm-linux-androideabi-clang"
    rustflags = [
        "-C", "link-arg=-L/实际路径/buildozer/python/lib/armeabi-v7a",
        "-C", "link-arg=-lpython3.10",
        "-C", "link-arg=-Wl,-rpath=$ORIGIN"
    ]
    
    [target.i686-linux-android]
    ar = "/home/feluk6174/rust/doxa_api/NDK/x86/bin/i686-linux-android-ar"
    linker = "/home/feluk6174/rust/doxa_api/NDK/x86/bin/i686-linux-android-clang"
    rustflags = [
        "-C", "link-arg=-L/实际路径/buildozer/python/lib/x86",
        "-C", "link-arg=-lpython3.10",
        "-C", "link-arg=-Wl,-rpath=$ORIGIN"
    ]
    

    替换/实际路径为你本地的Buildozer工作目录路径。

  3. 对齐cpython crate与Python版本
    在Cargo.toml中明确指定cpython版本和对应Python特性,避免版本不兼容:

    [dependencies]
    cpython = {version = "0.18", features = ["extension-module", "python310"]}
    
  4. 重新编译打包
    执行cargo build --target aarch64-linux-android --release重新编译Rust库,将生成的doxa_api.so复制到Kivy应用目录,再用Buildozer重新打包应用。

额外注意事项

  • 若链接时提示找不到Python库,检查库文件名是否为libpython3.so,调整-l参数对应的库名。
  • 确保Rust交叉编译使用的NDK版本与Buildozer使用的NDK版本一致,避免链接兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 17:11:16