Pregunta

Estoy empaquetando código C++ existente desde un BSD proyecto en nuestro propio contenedor personalizado y quiero integrarlo a nuestro código con la menor cantidad de cambios posible.Este código utiliza fprintf imprimir en stderr para registrar/informar errores.

Quiero redirigir esto a un lugar alternativo dentro del mismo proceso.En Unix He hecho esto con un socketpair y un thread:un extremo del zócalo es donde envío stderr (a través de una llamada a dup2) y el otro extremo se monitorea en un hilo, donde luego puedo procesar la salida.

Esto no funciona en ventanas aunque porque un socket no es lo mismo que un identificador de archivo.

Todos los documentos que encontré en la web muestran cómo redirigir la salida de un proceso secundario, que no es lo que quiero.¿Cómo puedo redirigir? stderr ¿Dentro del mismo proceso recibe una devolución de llamada de algún tipo cuando se escribe la salida?(y antes de que lo digas, lo he intentado SetStdHandle pero no puedo encontrar ninguna manera de hacer que esto funcione)...

¿Fue útil?

Solución

Puedes usar una técnica similar en Windows, solo necesitas usar palabras diferentes para los mismos conceptos.:) Este artículo: http://msdn.microsoft.com/en-us/library/ms682499.aspx usa una tubería win32 para manejar E/S de otro proceso, solo tienes que hacer lo mismo con los subprocesos dentro del mismo proceso.Por supuesto, en su caso, toda la salida a stderr desde cualquier parte del proceso será redirigida a su consumidor.

En realidad, otras piezas del rompecabezas que puedes necesitar son _fdopen y _open_osfhandle.De hecho, aquí hay un ejemplo relacionado de algunos código Lancé hace años:

DWORD CALLBACK DoDebugThread(void *)
{
    AllocConsole();
    SetConsoleTitle("Copilot Debugger");
    // The following is a really disgusting hack to make stdin and stdout attach
    // to the newly created console using the MSVC++ libraries. I hope other
    // operating systems don't need this kind of kludge.. :)
    stdout->_file = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
    stdin->_file  = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT);
    debug();
    stdout->_file = -1;
    stdin->_file  = -1;
    FreeConsole();
    CPU_run();
    return 0;
}   

En este caso, el proceso principal fue un proceso GUI que no comienza en absoluto con los identificadores stdio.Abre una consola, luego coloca los controladores derechos en stdout y stdin para que la función debug() (que fue diseñada como una función interactiva stdio) pueda interactuar con la consola recién creada.Debería poder abrir algunas tuberías y hacer el mismo tipo de cosas para redirigir stderr.

Otros consejos

Debe recordar que lo que MSVCRT llama "identificadores del sistema operativo" no son identificadores de Win32, sino otra capa de identificadores agregada solo para confundirlo.MSVCRT intenta emular los números de identificador de Unix donde stdin = 0, stdout = 1, stderr = 2 y así sucesivamente.Los identificadores de Win32 están numerados de manera diferente y sus valores siempre son múltiplos de 4.Abrir la tubería y configurar todas las manijas correctamente requerirá ensuciarse las manos.Probablemente sea un requisito utilizar el código fuente de MSVCRT y un depurador.

Mencionas que no deseas utilizar una canalización con nombre para uso interno;Probablemente valga la pena señalar que la documentación para Creartubería() estados, "Las canalizaciones anónimas se implementan utilizando una canalización con nombre único.Por lo tanto, a menudo puedes pasar un identificador a una tubería anónima a una función que requiere un identificador a una tubería con nombre". Por lo tanto, le sugiero que escriba una función que cree una tubería similar con la configuración correcta para la lectura asíncrona.Tiendo a usar un GUID como una cadena (generada usando CoCreateGUID() y StringFromIID()) para darme un nombre único y luego crear los extremos del servidor y del cliente de la canalización con nombre con la configuración correcta para E/S superpuestas (más detalles sobre esto y el código aquí: http://www.lenholgate.com/blog/2008/02/process-management-using-jobs-on-windows.html).

Una vez que lo tengo, conecto un código que tengo para leer un archivo usando E/S superpuestas con un puerto de finalización de E/S y, bueno, luego recibo notificaciones asíncronas de los datos a medida que llegan...Sin embargo, tengo una buena cantidad de código de biblioteca bien probado que hace que todo suceda...

Probablemente sea posible configurar la canalización con nombre y luego simplemente hacer una lectura superpuesta con un evento en su OVERLAPPED estructurar y verificar el evento para ver si había datos disponibles...Sin embargo, no tengo ningún código disponible que haga eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top