2012-02-08 5 views
13

나는 안드로이드에서 실행되도록 기존 C 코드를 포팅 중입니다. 이 C 코드는 stdout/stderr에 많은 양의 출력을 씁니다. 이 출력을 메모리 버퍼 나 파일에 캡처해야 전자 메일로 보내거나 그렇지 않으면 공유 할 수 있습니다.NDK로 stdout/stderr 캡처하기

기존 코드를 수정하지 않고 어떻게하면됩니까?

참고 : 출력이 adb 또는 logcat으로 리디렉션되는 것에 대한이 질문은 NOT입니다. 출력을 장치에 로컬로 버퍼링해야합니다.

+0

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

답변

1

표준 출력 경로 1 및 stderr이를 아는 경로 2, 당신은 설정할 수 있습니다 : 내 쿼리를 해결하기 위해 표시되지 않습니다 다음 질문, 알고있다 출력 목적지가 되고자하는 새 경로를 stdout 및/또는 stderr로 강제 변환합니다. practical examples use dup or dup2에서이를 수행하는 방법을 보여주는 예가 있습니다.

+0

내가 안드로이드에 대한 특별한 것은 여기가 없다는 것을 지적하고 싶습니다. 이것은 대부분의 유닉스 계열 시스템에서 일을하는 정상적인 방법입니다. –

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

고유 한 스레드에서 실행하고 싶습니다. 나는 자바에서 스레드를 회전 한 후 Java 스레드 호출이 같은이 NDK 코드가 있습니다

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