Full C++ yet still see the darn console window

Apologies if this simple question has been answered before. I have been searching the forums and the docs/website and haven’t really found an answer.

I decided to go with a full C/C++ Panda 3D app (no python), so that I could avoid exposing source code and python console windows, which detract from a client-side game.

Yet I run my compiled exe (a mod of hello world just to be sure I’m not doing something that could be the culprit) and the console is still there outputting information. I am using pure Panda 3D (i.e. main, from the hello tutorial, not WinMain or any dependent code). I’m in release mode, not even allowing debug includes (though I tried it both ways…/DEBUG flag and removing it…no joy). So if the console is being created, it’s because of Panda 3D itself. I was assuming, perhaps wrongly, that Panda 3D would not use python if called from an C++ app.

I’ve seen postings about using ppythonw, etc. and altering your installation package…but again, if I’m purely in C/C++, why am I getting the console starting as part of my .exe starting?

Can I turn it off? And hopefully, programmatically turn it off? (i.e. not some weird tweaking when creating an installation pkg.)

Again, apologies if this was already asked/answered…if someone could point me to that thread, I would really appreciate it.

Panda 1.6XX

Best,
CG

The console window is coming from Microsoft, and is opened automatically for any app that defines an entry point called main() instead of WinMain(). This has nothing to do with Panda3D.

To avoid the console window opening, simply use WinMain() instead of main().

Incidentally, I believe you are mistaken about your reasons for selecting C++ over Python: there is no need to distribute source, and there is no need to open a console window, with a Python application.

David

Alternatively, if you want to do it programmatically on the fly for whatever reason, you could do something like:

	//Get Handle to Console
	HWND hConsole = GetConsoleWindow();

	//Set the Console to Hidden
	ShowWindow(hConsole,SW_HIDE);

	//Force an immediate redraw
	RedrawWindow(hConsole,NULL,NULL,RDW_UPDATENOW);

Note that you will still probably see it flash up when you run the program before it gets hidden if you use this method. Also note that if you want a console some of the time, but not always, you can always create one on the fly using AllocConsole.

If you simple don’t want a console at all, use the method drwr posted.

Thanks.
Yet Panda 3D is certainly outputting info to that window. So it’s certainly making use of the console app, too.

I really didn’t want to tie the app to the windows architecture. It seems like doing winmain would force me to add other windows specific code. I wanted to avoid os-specific ties, save for what panda did itself. There has to be a way to shut it down since obviously Panda3D doesn’t need it to create/paint windows of its own.

How would one not have the console appear when using python? or is that the pythonw workaround? And the packing/install programs I’ve seen don’t seem to really turn the .py into a binary format. From what I’ve read on the forums, they just seem to hide them in a file that can easily be read via winzip or other de-archivers. Is that incorrect?

For server side, I see no issue with .py scripts, you can protect them. But client side, you can’t…so a binary seemed a better way to go.

Thanks,
CG

Thanks to you both,
Looks like I’m stuck using Windows whether I like it or not, if only to turn off the console programmatically.

Sure wish there was a way Panda3D could just do that programmatically. But perhaps that feature is already planned…or perhaps it’s not an easy fix.

Best and thanks,
CG

I just looked at the code, looks like Panda3D doesn’t have any knowledge of the console at all - it just sends it to stdout by default (Which by default in windows goes to the console window when you have one and disappears into nothing when you dont).

So it does not require the window to be there - it “automatically” will handle the no console situation (Although you would have to manually redirect the notifications if you want to log them somewhere, I suppose).

There isn’t any additional code that would need to be tied to windows when using the WinMain method

But overall you are going to have to add one OS-specific part (either the code to hide the console, or definining your entry WinMain entry point) in order to supress the console.

You don’t have to limit yourself to Windows, though - while you do need windows-specific code, you can simply ifdef the calls using _WIN32. Example:

#ifdef _WIN32
#include <windows.h>
#endif

...


void HideSystemConsole()
{
#ifdef _WIN32
  //Get Handle to Console 
   HWND hConsole = GetConsoleWindow(); 

   //Set the Console to Hidden 
   ShowWindow(hConsole,SW_HIDE); 

   //Force an immediate redraw 
   RedrawWindow(hConsole,NULL,NULL,RDW_UPDATENOW); 
#endif
}
int main(int argc,char** argv)
{
    HideSystemConsole();
    //...
}

or

#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#endif

...

#ifdef _WIN32
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
#else
int main(int argc,char** argv)
#endif
{
...
}

I’m not too familiar with Python yet, so I can’t answer the console question about python, but for the rest, you can compile Python to byte-code (in fact, it automatically does this when you run it.). This (.pyc files) can then be distributed instead of the source code. I think what the installers/packagers do is package the python script and something to launch the python script into a single executable (archive). While this file itself can be uncompressed, if the python inside it is already compiled, all that would be visible is the launcher and the pyc files. I don’t know enough about the options available for this to know which installers auto-convert to pyc, which ones allow pyc, and which (if any) only allow .py.

[Edited: Updated how the console works after looking at the code and added example for ifdefing out the hiding.]
[Edited: Added example for WinMain Ifdefing]

Very cool, thanks for going to so much trouble.

Python isn’t my strong suit either, though I like the idea of using it as a user scripting language within a VW/game…as a restricted execution environment…to which it happily lends itself easily.
Best!

Just a follow up, for those interested. I tried to find another clever way to trick Windows into doing my bidding,
but I failed.

Looks like best way around console in Windows is the _tWinMain option, as already told to me.

i.e.

#ifdef _WIN32 
#include <windows.h> 
#include <tchar.h> 
#endif 

#ifdef _WIN32 
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) 
#else 
int main(int argc, char *argv[]) 
#endif

Though you also need to modify your call to the framework, for example you could do the following:

 #ifdef _WIN32
// 
// I'm being lazy and not reading/converting lpCmdLine
// into argv, i.e. parsing the LPSTR, to get argc and 
// making sure that the pointer to the string is what
// argv expects, but 
// a fuller expansion should, of course.  
//
// You could use the Windows APIs, GetCommandLine() and/or
// GetCommandLineW() and/or CommandLineToArgvW(), but
// then you are using kernel32.lib and once
// again creating a dependency.
//
  int argc = 0;
  char **argv = NULL;
  framework.open_framework(argc, argv);
  #else
  framework.open_framework(argc, argv);
  #endif

The other method of using ShowWindow, etc. to hide the console, requires a change to the linker as well, as it wants the correct libraries.

As I am trying to avoid any Windows dependencies, I prefer the _tWinMain option instead. I found that while it needs the header files, it doesn’t need any linker changes (i.e. the linker doesn’t complain.) So it seems the most headache free route, and one with the least dependencies, and smaller code size since one less lib to link in.

I scoured my Windows Visual Studio documentation, trying to find a different route but came up empty.
There is a way to fool the linker, so that the console won’t appear. It’s used for ridding one of the console, when doing Windows Forms based applications. But that method, while ridding me of the console, also prevented Panda 3D from continuing execution. I tried several combinations and variations but Windows is stubborn, it wants that console. :slight_smile:

Second, I tried to intercept stdout messages in order to prevent the need for the console (as it only appears, apparently, because of stdout messages generated by Panda3D. Unfortunately, while I can reroute stdout/stderr within my program to a logfile I create, I cannot force this outside the scope of my program. In other words, I can’t force it for Panda3D. And it turns out the Windows documentation is actually clear about this point – i.e. redirecting stdout and like streams – they won’t let you. They say, point blank, that it is OS behavior to route to console and you cannot override (redirect) it, at least outside one’s own program.

However, I haven’t compiled the Panda3D source yet…no need yet… so I may try rerouting stdout within Panda3D (modding it, I mean, to use a logfile and not stdout) and see if the console goes away in Windows. How this might play out in other OS’s, I don’t know. Right now, I’m just working with Windows.

Again, thanks for the help. I appreciate it. It’s always the little things that turn out to be the most irritating on a project, and not the glamour stuff like renderers, and so forth.

Best,

I think you’re barking up the wrong tree just a little bit. The presence of the console window has absolutely nothing to do with whether there is any text written to stdout or not. Even if Panda3D never wrote anything to stdout, Windows would want to create a console window if your program begins with main(). It would just be an empty console window.

Conversely, if your program begins with WinMain(), Windows will not create a console window even though Panda3D is writing stuff to stdout. In this case, that Panda3D output is simply lost, and no harm done.

This is the whole point of WinMain(). It tells Windows not to create a console window. If you want to write platform-independent code that doesn’t create a console window on Windows, you have to use an #ifdef. Why resist this? It’s straightforward and easy, and it’s the way this problem is commonly solved.

(Unless, of course, you wrote your program in Python, where it is much easier to write platform-independent code without a series of conditions for each platform. But that’s a different discussion, I guess.)

David

There is no reason for the ifdef - you could just do

  int argc = 0;
  char **argv = NULL;
  framework.open_framework(argc, argv);

for both scenarios - as far as I can tell, the arguments aren’t used in the framework anyways.

Good catch - I wasn’t even thinking about linkage requirements.

I haven’t messed with configuration variables yet, so I don’t know the methods for setting them on a per-program basis, but for redirecting to a log file, you might want to look at the notify-output config variable and see if that would work.

Thanks David for clearing up the stdout v. Windows console bit. Pity there isn’t a more elegant solution, but Windows was pretty clear about forcing a console if you don’t use winmain (except for the Windows Forms app workaround, which didn’t work for Panda3D unfortunately.)

Since the console appears with either C++ or python use, on Windows at least, I’ll stick with C++ and #ifdefs as the easier solution for the client side, especially with the Apple ban on python and other languages that aren’t C/C++/Objective-C etc. Just seems an easier route for wide platform independence and acceptance.

Besides, I like C/C++. I’m hooked on pointers, I guess. ha ha! (sorry, bad pun)

And, Temaperacl, thanks again, though I’m not convinced yet that there won’t be arguments coming in, so I don’t want to throw away the argv stuff as a result. I was just in a hurry so didn’t write the code for parsing lpCmdLine, and more importantly, check it for accuracy before posting such code to an audience.

Again, thanks to both. Now to try to understand why Panda3D is so CPU intensive, 50%, even when the scene is already rendered and not changing.

Thanks,
C

pythonw eliminates the console for Python, but you already knew that. :slight_smile:

Welcome to the world of 3-D rendering. Unlike 2-D applications that typically spend a lot of time doing nothing while waiting for the user, and thus are optimized for the case in which nothing changes and stop rendering in that case, Panda (and almost every other 3-D engine in the world) is optimized for the case of rendering dynamic worlds that are constantly changing, and it doesn’t bother to handle the case of nothing changing. So it always re-renders the frame every time even though it is the same thing. Also, the general philosophy of a 3-D application is, take all of the resources you’ve got available. If you want to reduce the CPU utilization, there are options to do so (at the cost of frame rate or some such), but most people design their applications not to bother.

David

You can also set this:

#ifdef CONSOLE 
#pragma comment(linker, "/subsystem:console") 
#else 
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") 
#endif 

This allows you to switch to the windows subsystem while keeping your main() function - you wouldn’t have to create a WinMain. You can switch to the console subsystem by defining CONSOLE in the compiler definitions.

I can understand this behavior fine when the app has the focus, but it’s not the way 3D I’ve seen behaves when it loses the focus. A console app that gets to be sole owner of the cpu is one thing, but a PC app, like a VW or game, should be more malleable.

This is the only way to throttle this behavior? I’m concerned because this isn’t the behavior I observe with other 3D systems, like OpenSim for example. True, it takes about 50% when the viewer has the focus, but when another window has the focus, it drops quickly to 13-15% (on my system). Panda3D keeps it at 48-50% regardless of who has the focus, or number of open Panda3D windows (one Panda window or two, same 50% for one Panda exe, with two Panda exe’s–and their windows–it divides the 50% between the two exes and all their windows), or the usage reqs of the other apps. This is troubling behavior for using Panda3D as a VW that needs to share with other apps.

So there is no automatic way for it to behave civilly and throttle down when it loses the focus to another application? Bummer, so I’d have to force a frame rate drop in my program whenever I lose focus? Assuming I can tell I’ve lost focus–looks like more os-dependent code, double bummer.

Thanks,
CG

Thanks, that was one of the workarounds I was trying (the one used for Windows Forms apps), but I didn’t try it with mainCRTStartup as the entry point, just main, as per the MSFT docs. I’ll try this entry and see if it works any better.

Thanks,
CG

There is Python code in ShowBase.py to automatically reduce the CPU consumption when the Panda window is minimized, but this code doesn’t exist on the C++ side so you’ll have to add it yourself. Fortunately this is easy, and not platform-specific: you just need to listen for the window-event and check the WindowProperties for foreground and/or minimized properties to determine if your window has the focus or if it is minimized.

To reduce the CPU consumption, you only need to sleep a little bit in a task, like 0.1 seconds or so.

David

Thanks for the heads up, David.
Appreciated!
C