2012-02-08 20 views
13

私はAndroid上で動作するように既存のCコードを移植しています。このCコードは、stdout/stderrに大量の出力を書き込みます。この出力をメモリバッファまたはファイルに取り込む必要があるので、電子メールで送信したり、共有したりすることができます。NDKでstdout/stderrをキャプチャ

私はこれを、理想的には既存のCコードを変更することなく達成できますか?

注:出力がadbまたはlogcatにリダイレクトされることについてのこの質問はNOTです。出力をローカルにデバイスにバッファリングする必要があります。

+0

C++ http://stackoverflow.com/questions/8870174/is-stdcout-usable-in-android-ndkl –

答えて

1

stdoutがパス1であるとstderrはこれを知ってパス2である、あなたが確立することができます:私は私のクエリに対処するためには表示されません。次の質問の承知しています出力先になりたい新しいパスをstdoutまたはstderrに強制します。 practical examples use dup or dup2にこれを行う方法の例があります。

+0

私はアンドロイドについて何も特別なことはここではありませんことを指摘したいと思います。これは、ほとんどのUnixライクなシステム上でやり方をする通常の方法です。 –

17

stderrをパイプにリダイレクトするには、このような方法を使用します。パイプの反対側にある読者にlogcatへの書き込みを依頼してください:

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

これは独自のスレッドで実行します。私はこのような、このNDKコードをJavaでスレッドをスピンアップして、Javaスレッドの呼び出しを持っている:

new Thread() { 
    public void run() { 
     nativePipeSTDERRToLogcat(); 
    } 
}.start(); 
+2

このコードはファイル記述子をリークします。 'dup2()'の呼び出しの後に 'close(pipes [1]')する必要があります。また、これらのシステムコールのいずれかが失敗した場合は、どうすればよいか分かりませんが、エラーをチェックする必要があります。 –

1

私はジェームズ・ムーアが提出した答えを使用しますが、私はオンとオフのログを有効にすることができるようにしたかったです。これで、mKeepRunningをfalseに設定してシャットダウンします。また、O_NONBLOCKフラグをファイルに追加して、もはやブロッキングコールではなくなりました。

int lWriteFD = dup(STDERR_FILENO); 

if (lWriteFD < 0) 
{ 
    // WE failed to get our file descriptor 
    LOGE("Unable to get STDERR file descriptor."); 
    return; 
} 

int pipes[2]; 
pipe(pipes); 
dup2(pipes[1], STDERR_FILENO); 
FILE *inputFile = fdopen(pipes[0], "r"); 

close(pipes[1]); 

int fd = fileno(inputFile); 
int flags = fcntl(fd, F_GETFL, 0); 
flags |= O_NONBLOCK; 
fcntl(fd, F_SETFL, flags); 

if (nullptr == inputFile) 
{ 
    LOGE("Unable to get read pipe for STDERR"); 
    return; 
} 

char readBuffer[256]; 

while (true == mKeepRunning) 
{ 
    fgets(readBuffer, sizeof(readBuffer), inputFile); 

    if (strlen(readBuffer) == 0) 
    { 
     sleep(1); 
     continue; 
    } 

    __android_log_write(ANDROID_LOG_ERROR, "stderr", readBuffer); 
} 

close(pipes[0]); 
fclose(inputFile);