c # передает указатель файла на неуправляемый dll c ++ для использования в stdout - PullRequest
4 голосов
/ 02 октября 2011

Пожалуйста, потерпите меня - я разработчик на C # с небольшим опытом работы с C ++, и это крутой курс обучения!

Из консольного приложения c # я вызываю некоторые методы из неуправляемой библиотеки C ++. DLL записывает в поток stdout, хотя это не было обнаружено консолью c #.

Я нашел следующий код, который я добавил в DLL C ++, которая теперь успешно отправляет содержимое "printf" на консоль c #.

#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>

void redirect_stdout()
{
int hConHandle;
long lStdHandle;
FILE *fp;
// allocate a console for this app
AllocConsole();
// redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
}

Пока AOK:

Что я хотел бы сделать, это перехватить стандартный вывод из DLL в поток c #, а не отправлять его на консоль. Я попробовал описанный здесь метод ( Перенаправление stdout + stderr в службе Windows C # ), который фиксирует вывод, однако приложение «вылетает» при закрытии программы («vshost.exe перестал работать») .

(Примечание: установка Console.SetOut () в потоке захватывает вывод c #, а не вывод c ++).

Так что я подумал, что если я использую метод "Filestream.SafeFileHandle.DangerousGetHandle()", чтобы получить дескриптор файлового потока из c # и передать его в метод C ++ redirect_stdout (), метод:

void redirect_stdout(FILE *passedInHandle)
{

    // allocate a console for this app
    AllocConsole();
    *stdout= *passedInHandle;
    setvbuf( stdout, NULL, _IONBF, 0 );
}

Когда я запускаю вышеуказанную версию, вывод из DLL больше не передается на консоль c #, однако файловый поток на стороне c # всегда пуст.

Может ли какой-либо эксперт дать указания, чтобы STDOUT записывал свой вывод в файловый поток c #? Я уверен, что сделал какую-то глупую ошибку о том, как этого добиться, или я не понимаю, как добиться того, что я пытаюсь сделать.

Спасибо за ваше время и вклад - очень признателен!

[EDIT]

ОК - я немного поиграл и изменил метод C ++ следующим образом:

void redirect_stdout(int passedInHandle)
{
    int hConHandle;
    long lStdHandle;
    FILE *fp;
    // allocate a console for this app
    AllocConsole();

    hConHandle = _open_osfhandle(passedInHandle, _O_TEXT);
    fp = _fdopen(hConHandle, "w");
    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );
}

Это также успешно заполняет поток c #, однако при закрытии консольного приложения c # приложение вылетает с ошибкой «vshost.exe перестал работать». Это та же ошибка, что и при использовании метода из Перенаправление stdout + stderr в службе Windows C #

Очень странная находка: Если я запускаю консольное приложение "за пределами visual studio" (например, дважды щелкните по файлу .exe в папке bin), сбой не происходит!

Итак, я думаю, что мой следующий вопрос: как я могу отследить источник этого сбоя? Это связано с VS? Это происходит либо в режиме отладки, либо в режиме выпуска при запуске из VS, и не вызывает сбоя при запуске вне VS.

Я в недоумении, как отладить этот!

1 Ответ

1 голос
/ 03 октября 2011

Вы можете рассмотреть возможность использования именованных каналов: т.е.

связь между c ++ и c # через канал

http://www.switchonthecode.com/tutorials/interprocess-communication-using-named-pipes-in-csharp

Надеюсь, это должно сработать ...

...