Verwenden Sie C++ mit Android ndk/jni

Lesezeit: 5 Minuten

Benutzer-Avatar
pot2mayo

Alle ndk-Beispiele verwenden nur grundlegende C-Funktionen, die im Header als extern deklariert und in der cpp-Datei definiert sind. Nachdem Sie die Header-Datei in die C-Datei mit dem jni-Callback aufgenommen haben, funktioniert alles einwandfrei.

Ist es möglich, C++-Klassen mit dem Android-NDK zu verwenden? Meine Anwendung wird keine native Aktivität sein, sie wird immer noch einen wichtigen Java-Teil haben, aber sie wird nativen C-Code für CPU-intensive Berechnungen aufrufen (bereits in C++ geschrieben, mit Klassen und anderem C++-Zeug).

Hier ist meine Hallo-Welt-ähnliche Struktur für den Moment:

Datei “first.h”

#ifndef FIRST_H
#define FIRST_H

class Test
{};

#endif /* FIRST_H */

Datei “zweite.cpp”

#include <jni.h>
#include "first.h"

#ifdef __cplusplus
extern "C" {
#endif

jint Java_com_example_twolibs_TwoLibs_add( JNIEnv*  env,
                                      jobject  this,
                                      jint     x,
                                      jint     y )
{
    Test t;
    return 0;
}

#ifdef __cplusplus
}
#endif

Und schließlich Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libtwolib-second
LOCAL_SRC_FILES := second.cpp

include $(BUILD_SHARED_LIBRARY)

Ziemlich einfach, aber das kompiliert nicht. Das Umwandeln von second.cpp in eine .c-Datei löst einen Fehler aus, wenn die Header-Datei eingeschlossen wird, ich denke, das liegt daran, dass es sich nicht um eine C++-Datei handelt.

error: expected '=', ',', ';', 'asm' or '__attribute__' before 'Test'

Wenn Sie es .cpp machen, wird der folgende Fehler ausgegeben:

make: *** No rule to make target `/cygdrive/c/android-ndk-r5c/samples/twolibs/jni/second.c', needed by `/cygdrive/c/android-ndk-r5c/samples/two-libs/obj/local/armeabi/objs/twolib-second/second.o'.  Stop.

Irgendeine Idee, wie ich das Ding kompilieren kann?

Vielen Dank

Sie können C++ mit NDK verwenden, aber Dateien mit C++-Code müssen die Erweiterung .cpp haben.

Aus ANDROID-MK.html:

Beachten Sie, dass die Standarderweiterung für C++-Quelldateien „.cpp“ ist. Es ist jedoch möglich, einen anderen anzugeben, indem Sie die Variable LOCAL_CPP_EXTENSION definieren. Vergessen Sie nicht den Anfangspunkt (dh „.cxx“ funktioniert, aber nicht „cxx“).

  • Es scheint, als ob der Callback-C-Code (die Datei, die Aufrufe wie Java_com_example_twolibs_TwoLibs_add enthält, die von der Java-Seite aufgerufen werden sollen) in einer .c-Datei (nicht .cpp) enthalten sein muss. Andernfalls kompiliert es nicht auf meinem Computer. Wenn ich also versuche, eine Header-Datei einzufügen, die eine Klassendeklaration enthält, tritt derselbe Fehler auf.

    – pot2mayo

    22. Juni 2011 um 2:21 Uhr

  • Wenn ich alles in .cpp-Dateien umwandle, bekomme ich ein Make: *** No rule to make target error, was bedeutet, dass die Make-Datei die Quelldateien nicht finden konnte … aber es tut es, wenn ich sie in .c-Dateien umwandle, also ist dies keine Pfadproblem, denke ich

    – pot2mayo

    22. Juni 2011 um 2:37 Uhr

  • Es muss kompiliert werden, aber Sie müssen hinzufügen external "C" zu allen JNI-Funktionen. Haben Sie die Erweiterung der Quelldatei im Makefile geändert?

    – Michael

    22. Juni 2011 um 4:54 Uhr

  • Ja, ich habe versucht, extern “C” um jni-Funktionen hinzuzufügen (ich habe auch meinen Code in der Post aktualisiert), aber immer noch der gleiche Fehler “make: *** No rule to make target…”. Die Dateiendung ist auch in der Make-Datei korrekt

    – pot2mayo

    22. Juni 2011 um 5:26 Uhr


  • Ok, verstanden, Ihre Lösung war eigentlich richtig, aber ich habe vergessen, einige .o-Dateien zu bereinigen, deshalb suchte make immer noch nach der .c-Datei. Nachdem ich alles gereinigt und einen neuen ndk-build ausgeführt hatte, funktionierte alles einwandfrei. Vielen Dank!

    – pot2mayo

    22. Juni 2011 um 5:42 Uhr


Sie müssen alle nativen Bibliotheken speziell für Android neu kompilieren. Sie benötigen den Quellcode für alle nativen Bibliotheken von Drittanbietern, die Sie verwenden möchten, einfach weil sie normalerweise verknüpft sind, wenn wir diese Bibliotheken außerhalb von Android kompilieren und verknüpfen glibc aber leider Android nicht verwenden glibc aufgrund von Lizenz- und Leistungsproblemen. Android verwendet eine verwässerte Version von glibc genannt libc. Es hat für die meisten üblichen Funktionalitäten passende Symbolnamen zu glibc. Aber soweit ich weiß, hat die libc keine Funktionalität im Zusammenhang mit strings und es hat definitiv nicht einige posix Unterstützung. Wenn Ihre nativen Bibliotheken eine der veralteten Funktionen verwenden, müssen Sie eine Problemumgehung dafür finden, indem Sie alternative Funktionen verwenden, die von unterstützt werden libc und codieren Sie Ihre Bibliotheken entsprechend.

Wie Sie zu Recht darauf hingewiesen haben, müssen Sie das NDK verwenden, um Java (Android App/Fwk) mit der nativen Welt (C++) zu verbinden.

Obwohl dies meiner Erfahrung nach ziemlich einfach klingt, war das Kompilieren nativer Bibliotheken auf Android (Android-Portierung) traditionell sehr zeitaufwändig und ohne Erfolgsgarantie.

  • Danke für deine Antwort. Eigentlich kann ich nicht einmal anfangen, meine 3rd-Party-Libs zu portieren, da ich nicht einmal einen einfachen Hallo-Welt-ähnlichen Test zum Kompilieren bekommen kann, sobald ich Klassen darin verwende. Der erste Schritt wäre, eine fast leere zu erstellen native C++-Testklasse und verwende sie in meiner jni-Callback-C-Datei. Nur um zu sehen, ob das kompiliert.

    – pot2mayo

    21. Juni 2011 um 9:39 Uhr


Was Ihren Kompilierungsfehler betrifft, so haben Sie ihn anscheinend zuerst “second.c” genannt und später in “second.cpp” umbenannt, aber die Objektdateien enthalten immer noch den Namen “second.c”, also bevor Sie kompilieren (bdk-build) Sie müssen die *.o- und *.d-Dateien im Verzeichnis /cygdrive/c/android-ndk-r5c/samples/two-libs/obj/local/armeabi/objs/twolib-second/ entfernen

Fehler: ‘=’, ‘,’, ‘;’, ‘asm’ oder ‘__ Attribut __’ vor ‘Klasse’ erwartet

Klassischer Fall von fehlendem ‘;’ vor dem Schlüsselwort class? Vorstellen

 int functionname(int p)
 class X { } ;

Dies könnte ganz einfach zu Ihrer Compiler-Meldung führen. Ein häufiger erschwerender Faktor ist, wie es tatsächlich aussieht

 #include "someheader.h"
 class X { } ;

und der Fehler ist in der letzten Deklaration in someheader.h /oder einer rekursiv eingebundenen Datei/ 😉

Benutzer-Avatar
Ciro Santilli OurBigBook.com

Laufen:

ndk-build clean

nachdem Sie ein falsches geändert haben Android.mkoder der Build schlägt möglicherweise weiterhin fehl, selbst wenn Sie die Konfiguration korrigiert haben.

Ich denke, das hat das OP mit diesem Kommentar gemeint.

Benutzer-Avatar
QAlexkander Nicholson

Android.mk bearbeiten

Ändern Sie die Instanzen von LOCAL_SRC_FILES und entfernen Sie das ./ am Anfang jeder Zeile.

1384240cookie-checkVerwenden Sie C++ mit Android ndk/jni

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy