Android Android und native Standardeingabe und Standardausgabe

ColorFrog

Mitglied
Hallo,

welche Möglichkeiten gibt es die Texteingabe über das Edittext-Feld der Android-Umgebung in die Standardeingabe einer nativen C-Routine umzulenken. Und nach einer erfolgreichen Bearbeitung des Textes in der nativen C-Routine, die entsprechende Standardausgabe der C-Routine wieder in das Edittext-Feld wieder auszugeben?
 
Ganz richtig, natürlich ist der Weg über das NDK zu nehmen. Allerdings würde ich gerne wissen, mit welchen Routinen des Android-SDK bzw. Android-NDK man das bewerkstelligt.

Es sollte ungefähr so ablaufen wie im folgenden Pseudo-Code:

...
...
native C_Routine_einlesen();
native C_Routine_ausgeben();
...
...
in = Java_Routine (Standardeingabe_der_nativen_C_Routine_einlesen);
out = Java_Routine (Standardausgabe_der_nativen_C_Routine_ausgeben);
...
...
EditText(in);
EditText(out);
 
Ich bin dem aufgeführten Link gefolgt. Es behandelt aber nicht meine Problematik. Nach eigenen Recherchen, könnte ich mir aber durchaus vorstellen, dass die Sache doch nicht so knifflig ist wie ich dachte. Aber dennoch knifflig genug ist, um noch einmal diesen Aspekt zu thematisieren. Gibt es eine Möglichkeit folgenden Code editInput.getText().toString() in die Standardeingabe System.in zu schreiben. Und umgekehrt aus System.out in textResult.setText() reinzuschreiben?
 
Ich bin mir nicht sicher ob du nicht doch die Techniken aus meinem verlinkten Post verwenden musst um stdin und stdout von der C-Lib dazu zu bringen aber mal blöd gefragt: Hast du's schon ausprobiert mit nem Reader- bzw. Writer-Objekt auf System.in und System.out zuzugreifen?
 
So wie es aussieht lässt sich tatsächlich System.in nicht befüllen. Es lässt sich nur auslesen. Wogegen man in System.out nur Eingaben machen kann.

Der Link den du empfohlen hast, könnte die Lösung enthalten:

Java:
extern "C" void Java_com_test_yourApp_yourJavaClass_nativePipeSTDERRToLogcat(JNIEnv* env, jclass 
cls, jobject obj)
{
int pipes[2];
    pipe(pipes);
    dup2(pipes[1], STDERR_FILENO);
    FILE *inputFile = fdopen(pipes[0], "r");
    char readBuffer[256];
    while (1) {
        fgets(readBuffer, sizeof(readBuffer), inputFile);
        __android_log_write(2, "stderr", readBuffer);
    }
}

Welche native Android API müsste statt __android_log_write verwendet werden, um die Ausgabe in System.in bzw. System.out zu erhalten.

Da ich in Thread-Programmierung noch nicht so bewandert bin, stellt sich für mich die Frage ob im Java-Block tatsächlich ein neuer Thread erstellt werden muss und wie die Integration in Java im Allgemeinen aussehen muss?

Java:
new Thread() {
    public void run() {
        nativePipeSTDERRToLogcat();
    }
}.start();
 
Prinzipiell ist die Frage ob du mit den System.in nicht sowieso schon den Output der C-Komponente bekommst. Die Benennung ist ja immer diametral, je nachdem wo man ist. Ansonsten nach stdout schreiben.

Puncto Thread: das ist nötig. Aber aufpassen wegen des syncs, du musst mit postUpdate der view arbeiten.
 
Es scheint auch einen alternativen Weg zu geben, der die Nutzung von Pipes überflüssig macht, siehe dazu folgende Links:

http://http://developer.android.com/reference/java/io/FileDescriptor.html

http://http://developer.android.com/reference/java/io/FileInputStream.html

Wenn ich das richtig verstanden habe, bietet Java mit dem Filedescriptor über FileInputStream, FileOutputStream eben die Zugriffe zu stderr, stdin und stdout an.

Allerdings weiß ich nicht welche Objektkomponente von Android man nutzen kann, um in die Eingabe und Ausgabe zu schreiben. Es stellt sich die Frage, ob man etwa Edittext selber abwandeln muss, damit die Funktionalität passt.
 
Genau das habe ich mit meinem vorherigen Post gemeint. System.in ist ja ein InputStream und System.out ein PrintStream. Siehe dazu die Doku.

Die Frage die sich da jetzt nur stellt ist, ob das stdout und stdin der C-Komponente vom System in die selben Streams gemapped wird. Wenn ja, musst du so vorgehen:

1. Für System.in einen Thread aufmachen der die ganze Zeit liest. Damit bekommst du den Output. Den gelesenen Text kannst du dann immer wenn etwas daherkommt an dein EditText anhängen.
2. Wenn du vom anderen EditText den Text an die Komponente schicken willst nimmst du einfach System.out.println(txtBx.getText().toString());

Allerdings weiß ich eben nicht ob das ohne dem Umbiegen funktioniert.
 
Hallo Schlingel,

vielen Dank für deine meinem Anliegen entgegengebrachte Aufmerksamkeit.

Mir ist aber noch nicht ganz klar wie dein Vorschlag bei Punkt 1 funktionieren und als Code aussehen soll. Die Problematik, die ich habe ist einfach, dass die Eingabelogik von Java keine Möglichkeit anbietet Strings wie in C zum Beispiel über scanf() zum Einlesen anbietet.

Die normale in Java verwendete Eingabe- Ausgabelogik ist scheinbar getrennt von den Eingabekomponeten von Android wie beim Editext-Gefüge. Das bedeutet, soweit ich das sehe, dass der in eine Edittext eingebene Text nicht automatisch in Systen.in landet.

Der Code von Punkt 2 könnte funktionieren, indem man tatsächlich den Filedescriptor out als Korrespondenz für das stdout verwendet. Allerdings ist das alles bisher von mir bisher nur theoretisch betrachtet worden und gedanklich durchlaufen.

Mir ist dann allerdings noch einmal bei der Recherche in den Android-APIs eine weitere gute Möglichkeit aufgefallen, diie ich dich bitten würde, über folgenden Link anzusehen: ParcelFileDescriptor | Android Developers.

Da ist in einigen Methoden die Möglichkeit zur Nutzung von nativen Fildescriptoren. Es würde mich freuen wenn du dir Mühe machen würdest zu überlegen, welche Möglichkeiten sich dadurch ergeben. Immerhin, es scheint einen Weg zu geben.

In einem englischsprachigen Forum habe ich mein Anliegen zur Diskussion vorgetragen. Ich erhielt die Antwort, dass es überhaupt keine Möglichkeit gebe, da Android mit Linux als Basis (Dalvek JVM on top of kernel) anders aufgebaut sei als das übliche PC Linux (kernel + shell + window manager + ...). Aber dadurch das in den Android-APIs die Klasse ParcelFileDescriptor mit Ihrer Funktionalität vorhanden ist, nehme ich an, dass es auch einen eleganten Weg zur Lösung meines Anliegens geben sollte.
 
Naja, das Problem mit scanf vs. EditText ist ja viel allgemeiner. Da geht es um den Unterschied zwischen imperativer Programmführung und Ereignis orientierter Programmführung.

Aber prinzipiell stellt sich die Frage warum das so nicht funktionieren sollte. Du musst eben dem Benutzer eine geeignete View basteln die der C Komponente den String per System.out.println schickt.

Soll der ganze String geschickt werden? Dann könntest du das einfach per Button machen. Also der Benutzer bekommt eine Textbox, gibt den String ein und drückt dann auf den Button und die C-Komponente wird angeworfen.

Puncto ParcelFileDescriptor, das ist doch auch nur eine Android-Version eines InputStreams, den InputStream hast du ja bereits mit System.in.

Ich würd da weniger denken und einfach mal ausprobieren ob du die Lösung nicht eh schon hast.
 

Neue Themen


Zurück
Oben