Android NDK:未定义对“stderr"的引用 [英] Android NDK: undefined reference to 'stderr'
问题描述
我想在 Android 应用程序中使用 ASI SDK(预构建的二进制文件).我在 Windows 10 上使用 Android Studio 2.1.3 和 gradle实验插件"和 Android NDK r12b.
I want to use the ASI SDK (prebuilt binary) in an Android application. I am using Android Studio 2.1.3 on Windows 10 with the gradle "experimental plugin" and Android NDK r12b.
我的调用基本 SDK 函数的 JNI 测试方法如下所示:
My JNI test method that calls a basic SDK function looks as follows:
#include <jni.h>
#include <stdio.h>
#include <ASICamera2.h>
JNIEXPORT jstring JNICALL
Java_at_wana_androguide_MainActivity_getMsgFromJni(JNIEnv *env, jobject instance)
{
char str[512];
int numCams = ASIGetNumOfConnectedCameras();
snprintf(str, sizeof(str), "Connected cameras: %d", numCams);
return env->NewStringUTF(str);
}
app
模块的 build.gradle
如下所示:
The build.gradle
for the app
module looks like this:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig {
applicationId "at.wana.androguide"
minSdkVersion.apiLevel 19
targetSdkVersion.apiLevel 24
versionCode 1
versionName "0.1"
}
buildTypes {
release {
minifyEnabled false
proguardFiles.add(file('proguard-android.txt'))
}
}
ndk {
moduleName "hello-android-jni"
abiFilters.add("arm64-v8a")
abiFilters.add("x86")
stl "gnustl_static"
}
sources {
main {
jni {
dependencies {
library "ASISDK" linkage "static"
project ":usb" linkage "shared"
}
}
}
}
}
repositories {
libs(PrebuiltLibraries) {
ASISDK {
headers.srcDir "src/main/jni/drivers/ASI/include"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("src/main/jni/drivers/ASI/lib/${targetPlatform.getName()}/libASICamera2.a")
}
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.squareup:otto:1.3.8'
}
由于 ASI SDK 依赖于 libusb
,我还添加了 libusb
源作为单独的模块并作为依赖项导入到 app
模块.这是 libusb
模块(称为usb")的 build.gradle
文件:
Since the ASI SDK depends on libusb
, I also added the libusb
sources as a separate module and imported is as a dependency into the app
module. This is the build.gradle
file for the libusb
module (called "usb"):
apply plugin: "com.android.model.native"
model {
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
ndk {
moduleName "usb"
CFlags.add("-I${file("src/main/jni")}".toString())
CFlags.add("-I${file("src/main/jni/os")}".toString())
ldLibs.addAll(["log"])
}
}
}
问题:
此代码构建正常,但是当我在 Genymotion (x86)、Android 5 中运行它时,它会因运行时异常而崩溃:
This code builds OK, but when I run it in Genymotion (x86), Android 5, it crashes with a runtime exception:
java.lang.UnsatisfiedLinkError:dlopen 失败:无法定位符号libhello-android-jni.so"引用的stderr"..
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "stderr" referenced by "libhello-android-jni.so"..
我尝试将 supc++
和/或 stdc++
添加到 ldFlags
,我尝试将文件扩展名更改为 cpp
然后回到 c
,我已经尝试在 build.gradle 文件中将 platformVersion
设置为 19 甚至 9,但这只会导致编译时错误 说 stderr
没有定义:
I tried adding supc++
and/or stdc++
to ldFlags
, I tried changing the filename extension to cpp
and back to c
, and I already tried setting the platformVersion
to 19 or even 9 in the build.gradle files, but this only resulted in a compile time error saying that stderr
is not defined:
C:\Users\greuff\Documents\devel\AndroGuide\app\src\main\jni\drivers\ASI\lib\x86\libASICamera2.a(ASICamera2.o):ASICamera2.cpp:functionASIGetNumOfConnectedCameras:错误:未定义对stderr"的引用collect2.exe:错误:ld 返回 1 个退出状态
C:\Users\greuff\Documents\devel\AndroGuide\app\src\main\jni\drivers\ASI\lib\x86\libASICamera2.a(ASICamera2.o):ASICamera2.cpp:function ASIGetNumOfConnectedCameras: error: undefined reference to 'stderr' collect2.exe: error: ld returned 1 exit status
奇怪的是,这个错误只发生在 x86
平台目标上.
Curiously, this error only occurs for the x86
platform target.
我读到 stderr
等在某个时间点从 Android NDK 标头中删除,因为它们成为 libc
中的真正功能,但我不太确定如何解决这个问题,因为将 platformVersion
设置为较低的值(如某些问题中所建议的)没有帮助.我将非常感谢您提供正确方向的指点.
I read that stderr
etc were removed from Android NDK Headers at a certain point in time because they became real functions in libc
, but I'm not quite sure how to solve this problem since setting platformVersion
to a lower value (as suggested in some questions) did not help. I would be very grateful for pointers in the right direction.
推荐答案
事实证明我在追求错误的东西.ASI SDK 是针对包含 stderr
作为全局可用符号的 glibc 静态编译的,而仿生(Android libc)不包含它们.
Turns out I was chasing the wrong thing. The ASI SDK was statically compiled against the glibc which contains stderr
as globally available symbols, whereas bionic (the Android libc) doesn't contain them.
我所要做的就是取消定义 stderr
并将其创建为链接器符号,以便链接器可以找到它:
All I had to do was to undefine stderr
and created it myself as a linker symbol, so the linker can find it:
#include <jni.h>
#include <stdio.h>
#include <ASICamera2.h>
#undef stderr
FILE *stderr = &__sF[2];
...
这篇关于Android NDK:未定义对“stderr"的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!