cpp文件中的Android NDK未定义引用

时间:2020-05-03 15:42:39

标签: android c++ android-ndk java-native-interface

我正在尝试构建由Occipital Camera提供的Android NDK示例应用程序。

我的gradle文件是这样的:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.myoccipitaltestapp"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        ndk {
            abiFilters 'arm64-v8a'
        }

        externalNativeBuild {
            cmake {
                cppFlags '-std=c++11'
                arguments '-DANDROID_STL=c++_shared',
                        '-DANDROID_PLATFORM=android-24'
            }
        }

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    externalNativeBuild {
        cmake {
            path 'src/main/CMakeLists.txt'
        }

    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

我的CMakeLists.txt是(我必须硬编码MainActivity的路径,否则无法解决):

# Autogenerated, do not edit

    cmake_minimum_required(VERSION 3.6)
    project(MainActivity)
    add_library(MainActivity SHARED C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/cpp/MainActivity.cpp)
    set_target_properties(MainActivity PROPERTIES LINK_FLAGS "-Wl,-rpath,'$ORIGIN'")
    target_link_libraries(MainActivity PRIVATE
        ${PROJECT_SOURCE_DIR}/lib/${ANDROID_ABI}/libStructure.so
    )

带有JNI包装器的MainActivity.cpp是这样的:

// Autogenerated, do not edit

#include "AppInterface.h"
#include <jni.h>
#include <thread>

extern "C" JNIEXPORT void JNICALL Java_com_occipital_OccipitalTest_MainActivity_setupApp(JNIEnv*, jobject) {
    AppInterface::setup();
}

extern "C" JNIEXPORT void JNICALL Java_com_occipital_OccipitalTest_MainActivity_teardownApp(JNIEnv*, jobject) {
    AppInterface::teardown();
}

extern "C" JNIEXPORT void JNICALL Java_com_occipital_OccipitalTest_MainActivity_renderFrame(JNIEnv*, jobject, jint currentWidth, jint currentHeight, jfloat scaleFactor) {
    AppInterface::renderFrame((unsigned)currentWidth, (unsigned)currentHeight, scaleFactor);
}

extern "C" JNIEXPORT void JNICALL Java_com_occipital_OccipitalTest_MainActivity_updateMouseState(JNIEnv*, jobject, jboolean down, jint x, jint y) {
    AppInterface::updateMouseState(down, x, y);
}

extern "C" JNIEXPORT void JNICALL Java_com_occipital_OccipitalTest_MainActivity_plugStructureCoreFileDescriptor(JNIEnv*, jobject, jint fd) {
    AppInterface::plugStructureCoreFileDescriptor(fd);
}

AppInterface.h:

#pragma once

/** These functions define the interface between cross-platform sample
    application code and platform-specific wrappers. */
namespace AppInterface {
    /** On desktop platforms this function is called in main() before
        runUntilWindowClosed(). On Android it is called when the main activity
        is created. */
    void setup();

    /** On desktop platforms this function is called in main() after
        runUntilWindowClosed(). On Android it is called when the main activity
        is destroyed. */
    void teardown();

#if __ANDROID__
    /** See Window::renderFrameInGLSurfaceViewContext(). */
    void renderFrame(unsigned currentWidth, unsigned currentHeight, float scaleFactor);

    /** See Window::updateMouseState(). */
    void updateMouseState(bool down, int x, int y);

    /** For applications that require Structure Core USB support. The argument
        is a file descriptor from the Android UsbDeviceConnection API and should
        be passed to ST::registerSensorByUSBFileDescriptor() or equivalent. */
    void plugStructureCoreFileDescriptor(int fd);
#else
    /** Called in main(). */
    void runUntilWindowClosed();
#endif
}

MainActivity.java(已静态加载libStructure.so):

package com.example.myoccipitaltestapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.os.Bundle;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.usb.UsbDeviceConnection;
import android.Manifest;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.opengl.GLSurfaceView;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGLConfig;

public class MainActivity extends Activity implements com.example.myoccipitaltestapp.StructureCoreUSBHelper.Delegate, ActivityCompat.OnRequestPermissionsResultCallback {
    private class GLRenderer implements GLSurfaceView.Renderer {
        private MainActivity owner;
        private int width;
        private int height;

        public GLRenderer(MainActivity owner) {
            this.owner = owner;
        }

        public void onSurfaceCreated(GL10 gl, EGLConfig config) {}

        public void onSurfaceChanged(GL10 gl, int width, int height) {
            this.width = width;
            this.height = height;
        }

        public void onDrawFrame(GL10 gl) {
            owner.renderFrame(width, height, owner.scaleFactor);
        }
    }

    private class GLView extends GLSurfaceView {
        private MainActivity owner;
        private boolean mouseDown;

        public GLView(Context context, MainActivity owner) {
            super(context);
            this.owner = owner;
        }

        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
            switch (event.getActionMasked()) {
                case MotionEvent.ACTION_DOWN:
                    mouseDown = true;
                    owner.updateMouseState(mouseDown, (int)x, (int)y);
                    return true;

                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    mouseDown = false;
                    owner.updateMouseState(mouseDown, (int)x, (int)y);
                    return true;

                case MotionEvent.ACTION_MOVE:
                    owner.updateMouseState(mouseDown, (int)x, (int)y);
                    return true;

                default:
                    return false;
            }
        }
    }

    private GLView glView;
    private volatile float scaleFactor = 1.f;
    private com.example.myoccipitaltestapp.StructureCoreUSBHelper usbHelper;

    private float computeScaleFactor() {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        return metrics.density;
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupApp();

        scaleFactor = computeScaleFactor();
        glView = new GLView(this, this);
        glView.setEGLContextClientVersion(3);
        glView.setPreserveEGLContextOnPause(true);
        glView.setRenderer(new GLRenderer(this));
        glView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
        setContentView(glView);

        usbHelper = new com.example.myoccipitaltestapp.StructureCoreUSBHelper(this, this);
    }

    protected void onDestroy() {
        super.onDestroy();
        teardownApp();
    }

    public void onConfigurationChanged(Configuration config) {
        super.onConfigurationChanged(config);
        scaleFactor = computeScaleFactor();
        glView.requestRender();
    }

    protected void onPause() {
        super.onPause();
        glView.onPause();
    }

    protected void onResume() {
        super.onResume();
        glView.onResume();
        ActivityCompat.requestPermissions(this, new String[] {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
        }, 1);
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    }

    public void newStructureCoreDevice(UsbDeviceConnection conn) {
        plugStructureCoreFileDescriptor(conn.getFileDescriptor());
    }

    private native void setupApp();
    private native void teardownApp();
    private native void renderFrame(int currentWidth, int currentHeight, float scaleFactor);
    private native void updateMouseState(boolean down, int x, int y);
    private native void plugStructureCoreFileDescriptor(int fd);

    static {
        System.loadLibrary("Structure");
    }

/*
Also tried 

 static {
        System.loadLibrary("libStructure");
    }


*/

}

我在Android Studio中运行版本时,出现以下错误:

1)问题:

    Build command failed.
    Error while executing process C:\Users\Fsydn\AppData\Local\Android\Sdk\cmake\3.10.2.4988404\bin\ninja.exe with arguments {-C C:\Users\Fsydn\Desktop\occipital\StructureSDK-CrossPlatform-0.7.3-ROS\Libraries\MyOccipitalTestApp\app\.cxx\cmake\debug\arm64-v8a MainActivity}
    ninja: Entering directory `C:\Users\Fsydn\Desktop\occipital\StructureSDK-CrossPlatform-0.7.3-ROS\Libraries\MyOccipitalTestApp\app\.cxx\cmake\debug\arm64-v8a'
    [1/2] Building CXX object CMakeFiles/MainActivity.dir/cpp/MainActivity.cpp.o
    [2/2] Linking CXX shared library C:\Users\Fsydn\Desktop\occipital\StructureSDK-CrossPlatform-0.7.3-ROS\Libraries\MyOccipitalTestApp\app\build\intermediates\cmake\debug\obj\arm64-v8a\libMainActivity.so
    FAILED: C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/build/intermediates/cmake/debug/obj/arm64-v8a/libMainActivity.so 
    cmd.exe /C "cd . && C:\Users\Fsydn\AppData\Local\Android\Sdk\ndk\21.1.6352462\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android24 --gcc-toolchain=C:/Users/Fsydn/AppData/Local/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/Fsydn/AppData/Local/Android/Sdk/ndk/21.1.6352462/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security  -std=c++11 -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -Wl,--build-id -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments   -Wl,-rpath,'$ORIGIN' -shared -Wl,-soname,libMainActivity.so -o C:\Users\Fsydn\Desktop\occipital\StructureSDK-CrossPlatform-0.7.3-ROS\Libraries\MyOccipitalTestApp\app\build\intermediates\cmake\debug\obj\arm64-v8a\libMainActivity.so CMakeFiles/MainActivity.dir/cpp/MainActivity.cpp.o -LC:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/lib/arm64-v8a -lStructure -latomic -lm && cd ."
    CMakeFiles/MainActivity.dir/cpp/MainActivity.cpp.o: In function `Java_com_occipital_OccipitalTest_MainActivity_setupApp':
    C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/cpp/MainActivity.cpp:8: undefined reference to `AppInterface::setup()'
    CMakeFiles/MainActivity.dir/cpp/MainActivity.cpp.o: In function `Java_com_occipital_OccipitalTest_MainActivity_teardownApp':
    C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/cpp/MainActivity.cpp:12: undefined reference to `AppInterface::teardown()'
    CMakeFiles/MainActivity.dir/cpp/MainActivity.cpp.o: In function `Java_com_occipital_OccipitalTest_MainActivity_renderFrame':
    C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/cpp/MainActivity.cpp:16: undefined reference to `AppInterface::renderFrame(unsigned int, unsigned int, float)'
    CMakeFiles/MainActivity.dir/cpp/MainActivity.cpp.o: In function `Java_com_occipital_OccipitalTest_MainActivity_updateMouseState':
    C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/cpp/MainActivity.cpp:20: undefined reference to `AppInterface::updateMouseState(bool, int, int)'
    CMakeFiles/MainActivity.dir/cpp/MainActivity.cpp.o: In function `Java_com_occipital_OccipitalTest_MainActivity_plugStructureCoreFileDescriptor':
    C:/Users/Fsydn/Desktop/occipital/StructureSDK-CrossPlatform-0.7.3-ROS/Libraries/MyOccipitalTestApp/app/src/main/cpp/MainActivity.cpp:24: undefined reference to `AppInterface::plugStructureCoreFileDescriptor(int)'
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.

2)问题,Android IDE也在MainActivity.java中抱怨这些行

  private native void setupApp();
    private native void teardownApp();
    private native void renderFrame(int currentWidth, int currentHeight, float scaleFactor);
    private native void updateMouseState(boolean down, int x, int y);
    private native void plugStructureCoreFileDescriptor(int fd);

    cannot resolve corresponding JNI functions...

如何解决此问题以构建此示例应用?

0 个答案:

没有答案
相关问题