1. 報錯描述
使用 pthread 獲取線程名字, 用到 pthread_getname_np
函數。 交叉編譯到 Android NDK 時鏈接報錯
test_pthread.cpp:19:5: error: use of undeclared identifier 'pthread_getname_np'19 | pthread_getname_np(thread_id, thread_name, sizeof(thread_name));| ^
1 error generated.
ninja: build stopped: subcommand failed.
用到的構建腳本 build-android.ps1
:
$NDK="d:/soft/android-ndk/r28b"
$BUILD_DIR = "build-android"cmake `-S . `-B $BUILD_DIR `-G Ninja `-DCMAKE_TOOLCHAIN_FILE="$NDK/build/cmake/android.toolchain.cmake" `-DANDROID_ABI=arm64-v8a `-DANDROID_PLATFORM=21cmake --build $BUILD_DIR
用到的關鍵代碼: test_pthread.cpp
// 線程函數
void* hello(void* arg)
{char thread_name[16];pthread_getname_np(thread_id, thread_name, sizeof(thread_name));printf("Thread name: %s\n", thread_name);return NULL;
}
3. 分析和解決
3.1 pthread_getname_np 的 np 是什么意思?
是 non portable (不可移植) 的意思.
https://man7.org/linux/man-pages/man3/pthread_getname_np.3.html (參考鏈接[1])
hence the suffix “_np” (nonportable) in the names.
3.2 torchat issue 2
https://github.com/FraMecca/torchat/issues/2 (參考鏈接[2])
提問者貼出的編譯 log,看起來是 linux-x64 native 編譯。
倉庫 owner 回復說, 需要定義 _GNU_SOURCE
宏。
The issue is probably related to a missing #define _GNU_SOURCE .
嘗試在 test_pthread.cpp
開頭添加, 報錯不變。
3.3 pocoproject issue 4042
https://github.com/pocoproject/poco/issues/4042 (參考鏈接[5]) 報告了相同的錯誤, 是在 android armv7-a.
project member 和 contributor 的回答沒什么用處。 用戶已經包含了 pthread.h
頭文件。
3.4 從 bionic 找到答案
pthread 是在 Android bionic 庫里定義實現的。
git clone https://android.googlesource.com/platform/bionic # 參考鏈接[3]
以 pthread_getname_np
為關鍵字在 *.md
文件里搜索, docs\status.md
有說明:
https://android.googlesource.com/platform/bionic.git/+/refs/heads/main/docs/status.md#libc (參考鏈接[4]) 是它在線版:
New libc functions in O (API level 26):...* `pthread_getname_np`
意思是: pthread_getname_np()
是 API level 26 開始支持的.
因此解決方案是:修改 -DANDROID_PLATFORM=21
為 -DANDROID_PLATFORM=26
或更高版本:
build-android.ps1
:
$NDK="d:/soft/android-ndk/r28b"
$BUILD_DIR = "build-android"cmake `-S . `-B $BUILD_DIR `-G Ninja `-DCMAKE_TOOLCHAIN_FILE="$NDK/build/cmake/android.toolchain.cmake" `-DANDROID_ABI=arm64-v8a `-DANDROID_PLATFORM=26cmake --build $BUILD_DIR
4. 總結
pthread_getname_np()
是在 Android API 26 新增的函數, 在 cmake configure 階段需要傳入 -DANDROID_PLATFORM=26
或更高版本。 這在 Android C 標準庫 bionic 的文檔里有提及: https://android.googlesource.com/platform/bionic.git/+/refs/heads/main/docs/status.md 。
References
- [1] https://man7.org/linux/man-pages/man3/pthread_getname_np.3.html
- [2] https://github.com/FraMecca/torchat/issues/2 (方案無效)
- [3] https://android.googlesource.com/platform/bionic.git/
- [4] https://android.googlesource.com/platform/bionic.git/+/refs/heads/main/docs/status.md#libc
- [5] https://github.com/pocoproject/poco/issues/4042