Question

J'encapsule le code C++ existant à partir d'un BSD projet dans notre propre wrapper personnalisé et je souhaite l'intégrer à notre code avec le moins de modifications possible.Ce code utilise fprintf imprimer sur stderr afin de consigner/signaler les erreurs.

Je souhaite rediriger cela vers un autre endroit au sein du même processus.Sur Unix Je l'ai fait avec un socketpair et un thread:une extrémité de la prise est l'endroit où j'envoie stderr (via un appel à dup2) et l'autre extrémité est surveillée dans un thread, où je peux ensuite traiter la sortie.

Cela ne fonctionne pas sur les fenêtres mais parce qu'un socket n'est pas la même chose qu'un descripteur de fichier.

Tous les documents que j'ai trouvés sur le Web montrent comment rediriger la sortie d'un processus enfant, ce qui n'est pas ce que je souhaite.Comment puis-je rediriger stderr au sein du même processus, obtenir une sorte de rappel lorsque la sortie est écrite ?(et avant que tu le dis, j'ai essayé SetStdHandle mais je ne trouve aucun moyen de faire fonctionner cela)...

Était-ce utile?

La solution

Vous pouvez utiliser une technique similaire sous Windows, il vous suffit d'utiliser des mots différents pour les mêmes concepts.:) Cet article: http://msdn.microsoft.com/en-us/library/ms682499.aspx utilise un tube win32 pour gérer les E/S d'un autre processus, il vous suffit de faire la même chose avec les threads du même processus.Bien sûr, dans votre cas, toutes les sorties vers stderr depuis n'importe où dans le processus seront redirigées vers votre consommateur.

En fait, d'autres pièces du puzzle dont vous pourriez avoir besoin sont _fdopen et _open_osfhandle.En fait, voici un exemple connexe tiré de certains code J'ai sorti il ​​y a des années :

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

Dans ce cas, le processus principal était un processus GUI qui ne démarre pas du tout avec les handles stdio.Il ouvre une console, puis insère les bonnes poignées dans stdout et stdin afin que la fonction debug() (qui a été conçue comme une fonction interactive stdio) puisse interagir avec la console nouvellement créée.Vous devriez pouvoir ouvrir certains tuyaux et faire le même genre de chose pour rediriger stderr.

Autres conseils

Vous devez vous rappeler que ce que MSVCRT appelle « descripteurs du système d'exploitation » ne sont pas des descripteurs Win32, mais une autre couche de descripteurs ajoutée juste pour vous confondre.MSVCRT essaie d'émuler les numéros de handle Unix où stdin = 0, stdout = 1, stderr = 2 et ainsi de suite.Les handles Win32 sont numérotés différemment et leurs valeurs sont toujours un multiple de 4.Pour ouvrir le tuyau et configurer correctement toutes les poignées, vous devrez vous salir les mains.L'utilisation du code source MSVCRT et d'un débogueur est probablement une exigence.

Vous mentionnez que vous ne souhaitez pas utiliser de canal nommé pour un usage interne ;il vaut probablement la peine de souligner que la documentation pour Créer un tuyau() États, "Les tubes anonymes sont implémentés à l'aide d'un tube nommé avec un nom unique.Par conséquent, vous pouvez souvent transmettre un handle vers un tube anonyme à une fonction qui nécessite un handle vers un tube nommé." Je vous suggère donc d'écrire simplement une fonction qui crée un canal similaire avec les paramètres corrects pour la lecture asynchrone.J'ai tendance à utiliser un GUID comme chaîne (générée à l'aide de CoCreateGUID() et StringFromIID()) pour me donner un nom unique, puis créer les extrémités serveur et client du canal nommé avec les paramètres corrects pour les E/S superposées (plus de détails à ce sujet et le code ici : http://www.lenholgate.com/blog/2008/02/process-management-using-jobs-on-windows.html).

Une fois que j'ai cela, je câble du code que je dois lire un fichier en utilisant des E/S superposées avec un port de fin d'E/S et, eh bien, je reçois simplement des notifications asynchrones des données à mesure qu'elles arrivent...Cependant, j'ai une bonne quantité de code de bibliothèque bien testé qui permet à tout cela de se produire...

Il est probablement possible de configurer le canal nommé, puis de simplement effectuer une lecture superposée avec un événement dans votre OVERLAPPED structure et vérifiez l'événement pour voir si les données étaient disponibles...Cependant, je n'ai aucun code disponible pour faire cela.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top