简体   繁体   English

Android NDK:对'stderr'的未定义引用

[英]Android NDK: undefined reference to 'stderr'

I want to use the ASI SDK (prebuilt binary) in an Android application. 我想在Android应用程序中使用ASI SDK(预构建的二进制文件)。 I am using Android Studio 2.1.3 on Windows 10 with the gradle "experimental plugin" and Android NDK r12b. 我在Windows 10上使用Android Studio 2.1.3,带有gradle“实验插件”和Android NDK r12b。

My JNI test method that calls a basic SDK function looks as follows: 我调用基本SDK函数的JNI测试方法如下所示:

#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);
}

The build.gradle for the app module looks like this: app模块的build.gradle如下所示:

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'
}

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. 由于ASI SDK依赖于libusb ,我还将libusb源添加为单独的模块,并将其作为依赖项添加到app模块中。 This is the build.gradle file for the libusb module (called "usb"): 这是libusb模块的build.gradle文件(称为“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"])
        }
    }
}

Problem: 问题:

This code builds OK, but when I run it in Genymotion (x86), Android 5, it crashes with a runtime exception: 这段代码构建正常,但是当我在Genymotion(x86),Android 5中运行它时,它会因运行时异常而崩溃:

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "stderr" referenced by "libhello-android-jni.so".. java.lang.UnsatisfiedLinkError:dlopen失败:无法找到“libhello-android-jni.so”引用的符号“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: 我尝试添加supc++和/或stdc++ldFlags ,我试图改变文件扩展名来cpp和回c了,我已经试过设置platformVersion至19或的build.gradle文件,即使9,但这只是导致编译时间错误说没有定义stderr

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 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:错误:ld返回1退出状态

Curiously, this error only occurs for the x86 platform target. 奇怪的是,此错误仅发生在x86平台目标上。

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. 我读到stderr等在某个时间点从Android NDK Headers中删除了,因为它们在libc成为了真正的函数,但是我不太确定如何解决这个问题,因为将platformVersion设置为较低的值(如某些问题所示) ) 没有帮助。 I would be very grateful for pointers in the right direction. 我会非常感谢指向正确的方向。

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. ASI SDK是针对glibc静态编译的,其中包含stderr作为全局可用符号,而bionic(Android libc)不包含它们。

All I had to do was to undefine stderr and created it myself as a linker symbol, so the linker can find it: 我所要做的就是取消定义stderr并将其自己创建为链接器符号,以便链接器可以找到它:

#include <jni.h>
#include <stdio.h>
#include <ASICamera2.h>

#undef stderr
FILE *stderr = &__sF[2];

...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM