首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 專案編譯為 Android 可用 .so 動態庫完整流程

     編輯:程式設計疑難解答

核心工具鏈:NDK + CMake

Android 官方建議使用 CMake 作為建構系統,配合 NDK 工具鏈編譯 C/C++ 程式碼為 .so 動態共享庫,透過 JNI 供 Java/Kotlin 呼叫。

完整建構流程

1. 環境準備

  • Android Studio 安裝 NDK (SDK Manager → SDK Tools → NDK)
  • CMake 3.10+ (通常隨 Android Studio 安裝)
  • 專案結構:
project/
├── app/
│   ├── src/
│   │   ├── main/
│   │   │   ├── cpp/          # C++ 原始碼
│   │   │   │   ├── native-lib.cpp
│   │   │   │   └── include/  # 標頭檔
│   │   │   └── java/...      # Java/Kotlin 程式碼
│   │   └── CMakeLists.txt    # CMake 建構腳本
│   └── build.gradle

2. CMakeLists.txt 範例

cmake_minimum_required(VERSION 3.4.1)

# 設定 C++ 標準
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 專案名稱
project("my-native-lib")

# 匯入預編譯庫 (如有)
# add_library(imported-lib SHARED IMPORTED)
# set_target_properties(imported-lib PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libimported.so)

# 新增自有原始碼
add_library(
    native-lib           # 庫名稱 -> 編譯為 libnative-lib.so
    SHARED               # 動態庫
    native-lib.cpp       # 來源檔案
)

# 包含目錄
target_include_directories(native-lib PRIVATE include)

# 連結系統庫 (log, android, OpenGL ES 等)
find_library(log-lib log)
target_link_libraries(native-lib ${log-lib})

# 如需連結其他 .so
# target_link_libraries(native-lib imported-lib ${log-lib})

3. JNI 介面實作 (native-lib.cpp)

#include 
#include 
#include "my_cpp_class.h"

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapp_MainActivity_stringFromJNI(
    JNIEnv* env,
    jobject /* this */) {
    
    MyCppClass obj;
    std::string result = obj.processData("Hello from C++");
    return env->NewStringUTF(result.c_str());
}

// 多參數範例
extern "C" JNIEXPORT jint JNICALL
Java_com_example_myapp_Calculator_add(
    JNIEnv* env,
    jobject,
    jint a,
    jint b) {
    return a + b;
}

4. Java/Kotlin 端載入與宣告

// Java
public class MainActivity {
    static {
        System.loadLibrary("native-lib"); // 對應 CMake 中的 native-lib
    }
    
    public native String stringFromJNI();
    public native int add(int a, int b);
}

// Kotlin
class Calculator {
    companion object {
        init { System.loadLibrary("native-lib") }
    }
    external fun add(a: Int, b: Int): Int
}

5. build.gradle 設定

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions -std=c++17"
                arguments "-DANDROID_STL=c++_shared"
            }
        }
        ndk {
            abiFilters 'arm64-v8a', 'armeabi-v7a' // 指定架構,減少體積
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.18.1"
        }
    }
}

Windows 環境下交叉編譯 .so (命令列方式)

若需在 Windows 獨立編譯 (不使用 Android Studio):

# 設定 NDK 路徑
set NDK_ROOT=C:\Users\%USERNAME%\AppData\Local\Android\Sdk\ndk\25.1.8937393

# 使用 CMake 交叉編譯
cmake -B build -S . \
  -DCMAKE_TOOLCHAIN_FILE=%NDK_ROOT%\build\cmake\android.toolchain.cmake \
  -DANDROID_ABI=arm64-v8a \
  -DANDROID_PLATFORM=android-21 \
  -DANDROID_STL=c++_shared \
  -DCMAKE_BUILD_TYPE=Release

cmake --build build --config Release

常見問題與解決

問題原因解決
UnsatisfiedLinkError: 找不到 .so架構不匹配、庫名錯誤、未載入依賴檢查 abiFilters、System.loadLibrary 名稱、ldd 分析依賴
JNI 簽名不符Java native 宣告與 C++ 函式簽名不一致使用 javah 或 AS 自動生成標頭檔、核對參數型別
C++ 標準庫衝突c++_static vs c++_shared 混用統一使用 c++_shared,或所有模組同為 static
編譯錯誤: 標頭檔找不到include 路徑未正確設定CMake target_include_directories、NDK sysroot 路徑

參考資源

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved