Android NDK:对"stderr"的未定义引用 [英] Android NDK: undefined reference to 'stderr'
问题描述
我想在Android应用程序中使用ASI SDK(预构建的二进制文件).我正在Windows 10上使用带有gradle实验插件"和Android NDK r12b的Android Studio 2.1.3.
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
模块的build.gradle
文件(称为"usb"):
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
,并且我已经尝试将platformVersion
设置为19甚至9在build.gradle文件中,但这只会导致编译时错误,表示未定义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:功能 ASIGetNumOfConnectedCameras:错误:对"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屋!