WinMain Cannot be Overloaded


#1

Hey Jules,

When attempting in building a release version of my project, I’m getting the good ol’;

The errors persists whether or not I’m including Windows.h. On the other hand, everything works fine in debug!

Something tells me this is related to unicode crap…


#2

Yep.

Check “Configuration Properties, General, Character Set” and also, have a look at “Linker, System, SubSystem” make sure it’s set to “Windows (/SUBSYSTEM:WINDOWS)”


#3

Hm… the Character Set is set to Multi-Byte, and the subsystem is indeed set to ““Windows (/SUBSYSTEM:WINDOWS)”” for both Debug and Release. (so far, so good then?)

Something else is borking this…


#4

I’m guessing that the error happens in the START_JUCE_APPLICATION macro? The error happens because of a difference in TCHAR. The system include are declaring it one way (narrow or wide) and then something is changing.


#5

Ahhhh - damnit! A 3rd party library being included in the wrong order; after JuceHeader.h… Having it before fixes the issue.

Sorry if I’ve wasted your time…


#6

No waste at all. Analyzing the problem, is there any way that the JUCE headers could be modified to detect this condition and generate some sort of #error ?


#7

[quote]No waste at all.[/quote] ok :slight_smile:

I’m wondering the same. I’m searching for the macro flags involved to see if I can create some condition to utilize a #error.


#8

I have been trapped with this as well using some Boost stuff


#9

Hm… so it seems that the 3rd party library happened to be including Windows.h, and I was including the master library header after JuceHeader.h… instantly causing the WinMain conflict.

I wonder if there’s an indicator of some kind for knowing if Windows.h is being included or not.


#10

Actually, there is! The include guard for Windows.h: WINDOWS


#11

Hm… I’m still not sure why this all happens. Anybody know?

I don’t yet understand why there’s a conflict in the first place, and why the include order should matter.


#12

<windows.h> causes WINAPI to get defined, and JUCE uses LPSTR in the START_JUCE_APPLICATION macro for the declaration of WinMain. This is actually a bug in JUCE…

Try changing LPSTR to LPTSTR in juce_Initialisation.h and see if it works where it would previously generate an error.


#13

Jules designed juce_Initialisation.h to not need the include of <windows.h>, which is great. But if windows.h is included before the JUCE headers then there’s a problem, since it defines WINAPI and causes the alternate macro definition for START_JUCE_APPLICATION. I believe that this is the proper fix:

/*
    To start a JUCE app, use this macro: START_JUCE_APPLICATION (AppSubClass) where
    AppSubClass is the name of a class derived from JUCEApplication.

    See the JUCEApplication class documentation (juce_Application.h) for more details.

*/
#if JUCE_ANDROID
  #define START_JUCE_APPLICATION(AppClass) \
    juce::JUCEApplication* juce_CreateApplication() { return new AppClass(); }

#elif JUCE_WINDOWS && defined (WINAPI)
  #define START_JUCE_APPLICATION(AppClass) \
    static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \
    int WINAPI WinMain (HINSTANCE, HINSTANCE, LPTSTR, int) \
    { \
        juce::JUCEApplication::createInstance = &juce_CreateApplication; \
        return juce::JUCEApplication::main(); \
    }

#elif JUCE_WINDOWS && defined (_UNICODE)
  #define START_JUCE_APPLICATION(AppClass) \
    static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \
    int __stdcall WinMain (void*, void*, const wchar_t*, int) \
    { \
        juce::JUCEApplication::createInstance = &juce_CreateApplication; \
        return juce::JUCEApplication::main(); \
    }

#elif JUCE_WINDOWS
  #define START_JUCE_APPLICATION(AppClass) \
    static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \
    int __stdcall WinMain (void*, void*, const char*, int) \
    { \
        juce::JUCEApplication::createInstance = &juce_CreateApplication; \
        return juce::JUCEApplication::main(); \
    }

#else
  #define START_JUCE_APPLICATION(AppClass) \
    static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \
    int main (int argc, char* argv[]) \
    { \
        juce::JUCEApplication::createInstance = &juce_CreateApplication; \
        return juce::JUCEApplication::main (argc, (const char**) argv); \
    }

#endif

#14

The issue is actually the following; if I include windows.h at any point, intentionally or not (ie: a library includes it without me knowing), after the JuceHeader.h, the following version of WinMain becomes active (thus causing the “‘WinMain’: function cannot be overloaded” error):

#elif JUCE_WINDOWS
  #define START_JUCE_APPLICATION(AppClass) \
    static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \
    int __stdcall WinMain (void*, void*, const char*, int) \
    { \
        juce::JUCEApplication::createInstance = &juce_CreateApplication; \
        return juce::JUCEApplication::main(); \
    }

(This is with and without your modifications)


#15

if _UNICODE is defined then “const char*” should be “const w_char_t*” in the declaration of WinMain.


#16

Interesting thread!

How about this:

[code]/*
To start a JUCE app, use this macro: START_JUCE_APPLICATION (AppSubClass) where
AppSubClass is the name of a class derived from JUCEApplication.

See the JUCEApplication class documentation (juce_Application.h) for more details.

/
#if JUCE_ANDROID
#define START_JUCE_APPLICATION(AppClass)
juce::JUCEApplication
juce_CreateApplication() { return new AppClass(); }

#else
#if JUCE_WINDOWS
#ifdef _UNICODE
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const wchar_t*, int)
#else
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const char*, int)
#endif
#define JUCE_MAIN_FUNCTION_ARGS
#else
#define JUCE_MAIN_FUNCTION int main (int argc, char* argv[])
#define JUCE_MAIN_FUNCTION_ARGS argc, (const char**) argv
#endif

#define START_JUCE_APPLICATION(AppClass)
static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); }
JUCE_MAIN_FUNCTION
{
juce::JUCEApplication::createInstance = &juce_CreateApplication;
return juce::JUCEApplication::main (JUCE_MAIN_FUNCTION_ARGS);
}
#endif
[/code]


#17

Like I said, I tried with and without all of your suggested modifications in release, and to no avail.

These “replacements” still don’t solve the WinMain cannot be overloaded error… There’s something else causing this.


#18

It seems that I can only get WinMain to work if its params are explicitly the following:

Notes:
[list]
[] _UNICODE is not defined for me…[/][/list]

You must test this with the following header order in Main.cpp:

#include "JuceHeader.h"
#include <windows.h>

#19

[quote=“jrlanglois”]It seems that I can only get WinMain to work with the header order if its params are explicitly the following:

Notes: _UNICODE is not defined.[/quote]

Try LPTSTR. I think you want LPTSTR if WINAPI is defined, else use const wchar_t* if _UNICODE is defined, else use const char*.


#20

Even with WINAPI defined in this scenario, WinMain still needs to have the params I listed above to work, including using LPSTR.

Oddly enough, I have to explicitly use HINSTANCE, and not void*. It seems that HINSTANCE is a “struct” in this case, setup as such:

Here’s what I have, which works for me for every case that <windows.h> is included…

        #if defined(_UNICODE)
            #define JUCE_MAIN_FUNCTION       int __stdcall WinMain (void*, void*, const wchar_t*, int)
        #elif defined(WINAPI)
            #define JUCE_MAIN_FUNCTION       int __stdcall WinMain (HINSTANCE, HINSTANCE, const LPTSTR, int)
        #else
            #define JUCE_MAIN_FUNCTION       int __stdcall WinMain (HINSTANCE, HINSTANCE, const LPSTR, int)
        #endif