Solved

Why can't I write to MFC GUI console?

Posted on 1997-04-22
4
832 Views
Last Modified: 2013-11-20
I've developed a C++ Delaunay/Voronoi triangulation library which runs fine on several flavors of Unix as well as in NT
and Win95 console applications. The debug version of the library writes error and diagnastic information to STDOUT and STDERR as formatted text through cout and cerr.
 
Now I have an MFC GUI application to visualize the triangulations. I want to be able to allocate a console and have the diagnostic output from the triangulation library go to the console window without having to modify the library (so it still runs on Unix).
 
The application is a standard MFC app created with AppWizard. I can create the console window using AllocConsole()  ( in InitInstance() in the App ), but nothing gets written to it.
 
I tried to redirect STD_OUTPUT_HANDLE and STD_ERROR_HANDLE using SetStdHandle() but can't seem to get a handle to the newly created console's standard output and standard error. The docs for CreateFile() say to use CON and CONOUT&. What the hell are they? I grepped and searched for these but turned up nothing. What's going on here?
 
I noticed that before I created the console, GetStdHandle() returned 0 (no console) and after the call to AllocConsole() STD_OUTPUT_HANDLE was 7 (0x00000007). Is this a valid handle? (Doesn't work if it is!)

The docs for AllocConsole() say that the call sets up
(redirects) the std io handles. Why doesn't it work?

I include iostream.h header in the library so that it works with Unix and in console applications. When I build the MFC application I have to use the /NODEFAULTLIB switch to get it to link properly. I also noticed that when I run it from the build menu in devstudio, there are 2 io libraries loaded and one is relocated in memory (forget the exact message). Could this be the problem?

What am I doing wrong? Am I going about this all wrong? Should I be using CreateProsess() instead?
 
Any help would be appreciated.
 
Thanks
Todd
0
Comment
Question by:thj
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
4 Comments
 

Author Comment

by:thj
ID: 1301144
Adjusted points to 100
0
 

Expert Comment

by:juria
ID: 1301145
Microsoft's C stdio library initialize routine needs stdin, stdout, stderr HANDLE to be created at first to be used.

In this case, Console handle is created later than stdio init routine. There is no way to output to stdout or stderr.

The following will guide you to use low level and high level stdio
system.

1. call your CWinApp subclass as CTheApp.
2. include stdio.h at the top of CTheApp constructor.
3. define following above CTheApp's constructor.
    extern      "C" {
    void __cdecl _ioinit (void) ;
    } ;
4. add following to your CTheApp's constructor.
CTheApp::CTheApp()
{
    HANDLE hHandle;
    BOOL bRet;
    // Create Console if not have
    hHandle = GetStdHandle(STD_INPUT_HANDLE);
    hHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    hHandle = GetStdHandle(STD_ERROR_HANDLE);
    if ( hHandle == 0 ) {
        bRet = AllocConsole();

        hHandle = GetStdHandle(STD_INPUT_HANDLE);
        hHandle = GetStdHandle(STD_OUTPUT_HANDLE);
        hHandle = GetStdHandle(STD_ERROR_HANDLE);

        // reinitialize io subsystem
        _ioinit ();

        // reinitialize FILE stdio
        _iob[0]._file = 0;
        _iob[1]._file = 1;
        _iob[2]._file = 2;
    }

    // TODO : add other initialize code
}

5. Change project's setting to use MFC static library.
    This is needed to use _ioinit. Indeed use static C library.

I tested using VC4.2 and windows NT 4.0

0
 

Accepted Solution

by:
davem043097 earned 100 total points
ID: 1301146
-Call AllocConsole() in InitInstance() as you're doing now.-Call a new function in your dll called InitIOStream() (see below for implementation)-cout and cerr should now work in the dll************test.dll************#include <iostream.h>
#include <io.h>
#include <FCNTL.H>
#include <fstream.h>
#include <windows.h>

void __declspec(dllexport) InitIOStream()
{
    int fd;    //get file descriptor of console's stderr    fd = _open_osfhandle((long) GetStdHandle        STD_ERROR_HANDLE),_O_TEXT);    //create unbuffered file stream based on stderr
    static ofstream mycerr(fd, NULL, 0);
    //get file descriptor of console's stdout    fd = _open_osfhandle((long) GetStdHandle        (STD_OUTPUT_HANDLE),_O_TEXT);    //create unbuffered file stream based on stdout    static ofstream mycout(fd, NULL, 0);
   //re-assign cerr and cout to our new streams    cerr = mycerr;
    cout = mycout;
    cerr << "cerr initialized" << endl;
    cout << "cout initialized" << endl;
}

void __declspec(dllexport) TestCerr()
{
    cerr << "hello from cerr in a dll" << endl;
}

void __declspec(dllexport) TestCout()
{
    cout << "hello from cout in a dll" << endl;
}
0
 
LVL 1

Expert Comment

by:bcrotaz
ID: 3407810
thj -

I'm currently looking for a Win2K triangulation DLL.  Could you send me details of your one?  

Bryan
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
If you're a developer or IT admin, you’re probably tasked with managing multiple websites, servers, applications, and levels of security on a daily basis. While this can be extremely time consuming, it can also be frustrating when systems aren't wor…

696 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question