Weird Error in WinMain() to main() Macro - c

/** converts 'WinMain' to the traditional 'main' entrypoint **/
#define PRO_MAIN(argc, argv)\
int __main (int, LPWSTR*, HINSTANCE, int);\
int WINAPI WinMain (HINSTANCE __hInstance, HINSTANCE __hPrevInstance, \
LPSTR __szCmdLine, int __nCmdShow)\
{\
int nArgs;\
LPWSTR* szArgvW = CommandLineToArgvW (GetCommandLineW(), &nArgs);\
assert (szArgvW != NULL);\
return __main (nArgs, szArgvW, __hInstance, __nCmdShow);\
}\
\
int __main (int __argc, LPWSTR* __argv, HINSTANCE __hInstance, int __nCmdShow)
Now, when I use this code here:
PRO_MAIN(argc, argv)
{
...
}
I get the error:
error: conflicting types for '__main'
note: previous declaration of '__main' was here
What's the problem?

You have broken the rules: double-underscores are reserved for implementation! (Among other things.)
You simply cannot use __main, main__, _Main, etc. You should pick something else.
I would recommend you make this work:
int main(int argc, char* argv[])
{
// main like normal
}
// defines WinMain, eventually makes call to main()
PRO_MAIN;
Which has the added advantage that for non-Windows applications, PRO_MAIN can simply expand to nothing, and the program still compiles with the standard main function. This is what I do.

Related

Function visibility in C : make function visible and callable through macro only (MSVC compiler)

I would like to make function to be callable (e.g. exposed) to the rest of the library through the macro only, to prevent accidental undesired side effects.
Why? This is because I have a variadic function, which could be called from another variadic function and that way I would like to add NULL sentinel to the call, using macro, thus making access to va_list much easier and prevent undefined behaviour. There are also other handy scenarios, where this could really be helplful.
An example :
test.h
void _func(char *dummy, ...);
//I would like to make sure that rest of the library
//only calls _func through this macro
#define func(dummy, ...) _func(dummy, __VA_ARGS__, NULL)
test.c
//Implementation of the _func function
static void _func(char *dummy, ...) {
//body goes here...
}
main.c
int main(int argc, char *argv[]) {
//This should not be allowed by compiler
_func("dummy", "arg1");
//This should be allowed by compiler, but since definition
//of _func is static in test.c file, compiler is not happy anyway
//LNK2001 unresolved external symbol __func
func("dummy", "arg1");
return 0;
}
I've already tried with #define and #undef compiler directives to somehow force this scenario, but no avail. Is this even possible in C?
You can shadow the function with a macro:
void _func(char *dummy, ...);
#define _func(...) error_use_the_macro_func_instead_of_calling__func_directly
// Always use the macro "func" instead of calling "_func" directly.
#define func(dummy, ...) (_func)(dummy, __VA_ARGS__, NULL)
Notice the parentheses around _func in the macro. This prevents the _func from being recognized as a function-like macro and gives the macro access to the function. If somebody tries to call _func directly, they get
error C2065: 'error_use_the_macro_func_instead_of_calling__func_directly': undeclared identifier
This "macro shadowing" technique has the advantage of being usable in expression contexts:
for (int i = 0; i < 5; func("incrementing i", ++i)) { ... }
or if we change the situation slightly and give _func a return value:
int _func(char *dummy, ...);
#define _func(...) error_use_the_macro_func_instead_of_calling__func_directly
// Always use the macro "func" instead of calling "_func" directly.
#define func(dummy, ...) (_func)(dummy, __VA_ARGS__, NULL)
then this allows you to do things like
int i = func("hello", 2) * func("there", 3);
Maybe you can scope the visibility of the private function? Here's a snippet to illustrate what I mean. Not pretty, but it may work for you(no MSVC to test with here)
#define func(a, b) do { \
extern void private_func(int , int );\
private_func(a, b);\
} while (0)
void foo(void)
{
func(1, 2);
private_func(3, 4);
}
What #Bjorn A. has written in the post above, actually solves my problem as compiler gets angry with the message : '_func': redefinition; different basic types if I try to call _func directly.
Here is the adopted example :
test.h
#define func(dummy, ...) do { \
extern void _func(char *, ...);\
_func(dummy, __VA_ARGS__, NULL);\
} while (0)
test.c
//Implementation of the _func function
//static has to be omitted here, but it doesn't matter
void _func(char *dummy, ...) {
//body goes here...
}
main.c
int main(int argc, char *argv[]) {
//'_func': redefinition; different basic types
//if we try to call _func directly
_func("dummy", "arg1");
//this is ok
func("dummy", "arg1");
func("dummy2", "arg2");
return 0;
}
EDIT : Actually, #Raymond Chen has proposed much better solution with function shadowing - idea is to enclose the function name with parentheses to stop preprocessor from expanding it. More info about that here.
Here is the final (hopefully) solution that works like a charm :
test.h
void _func(char *dummy, ...);
#define _func(...) error_use_the_macro_func_instead_of_calling__func_directly
#define func(dummy, ...) (_func)(dummy, __VA_ARGS__, NULL)
test.c
//Notice the _func is enclosed with parentheses here
void (_func)(char *dummy, ...) {
//body goes here...
}
main.c
int main(int argc, char *argv[]) {
//C2065 'error_use_the_macro_func_instead_of_calling__func_directly': undeclared identifier
//if we try to call _func directly
_func("dummy", "arg1");
//this is ok
func("dummy", "arg1");
func("dummy2", "arg2");
return 0;
}
Many thanks! Cheers!

How to use macro for calling function?

I want to call function according to func_name string.
My code is here below:
#define MAKE_FUNCNAME func_name##hello
void call_func(void* (*func)(void))
{
func();
}
void *print_hello(void)
{
printf("print_hello called\n");
}
int main(void)
{
char func_name[30] = "print_";
call_func(MAKE_FUNCNAME);
return 0;
}
But this code doesn't work. I want code to work like call_func(print_hello). But preprocessor treated my code like call_func("print_hello"). How to use macro in C to make my exception? Or is it not possible using C?
Then problem with your code is that the value of func_name is only known at run-time.
You can however to it like this:
#define MAKE_FUNCNAME(FUNCNAME) FUNCNAME##hello
void call_func(void* (*func)(void))
{
func();
}
void *print_hello(void)
{
printf("print_hello called\n");
}
int main(void)
{
call_func(MAKE_FUNCNAME(print_));
return 0;
}
But it is not possible to use a string value within macro parameters like in your code snippet.
If you want to get call functions with their names using string values you can use a table to store function pointer with function names like this:
struct {
const char *name;
void (*ptr)(void);
};
You can use an array of this structure to find out the function pointer at run-time using a string value. This is the most common solution to using run-time strings to call functions using their names.
You can't do that. The value of func_name is known at run-time (even though it is a const char *), while you want to determine what to call at precompile-time. You should turn your cpp macro into something different (such as an if/switch statement or using an indirection).
Maybe you could have a look to dlsym().
Not sure I really understand the question, but if you want to "build" the function name at runtime and then call the corresponding function, it should be possible with dlsym()
/* compile with: gcc example.c -ldl -rdynamic */
#include <dlfcn.h>
#include <stdio.h>
int print_hello(void)
{
return printf("hello\n");
}
int main(int argc, char *argv[])
{
const char *name = "print_hello";
if (argc == 42)
print_hello(); /* for compiler not to remove print_hello at
* compile time optimisation in this example*/
void *handle = dlopen(NULL /* self */, RTLD_NOW);
int (*f)(void) = dlsym(handle, name);
f();
return dlclose(handle);
}

What is the meaning of CDECL in this code?

here I have a code from the book programming windows fifth edition.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, ...)
{
TCHAR szBuffer[1024];
va_list pArgList;
// The va_start macro (defined in STDARG.H) is usually equivalent to:
// pArgList = (char *) &szFormat + sizeof (szFormat) ;
va_start(pArgList, szFormat);
// The last argument to wvsprintf points to the arguments
_vsntprintf(szBuffer, sizeof (szBuffer) / sizeof (TCHAR),
szFormat, pArgList);
// The va_end macro just zeroes out pArgList for no good reason
va_end(pArgList);
return MessageBox(NULL, szBuffer, szCaption, 0);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
int cxScreen, cyScreen;
cxScreen = GetSystemMetrics(SM_CXSCREEN);
cyScreen = GetSystemMetrics(SM_CYSCREEN);
MessageBoxPrintf(TEXT("ScrnSize"),
TEXT("The screen is %i pixels wide by %i pixels high."),
cxScreen, cyScreen);
return 0;
}
what is the meaning of CDECL after int in below code?
int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, ...)
In the windows header files, CDECL is defined like this:
#define CDECL
This seems a little odd. It is a macro that expands to nothing. Used where a calling convention is expected it results in the default calling convention, namely __cdecl.

argument of type const char* is incompatible with parameter of type "LPCWSTR"

I am trying to make a simple Message Box in C in Visual Studio 2012, but I am getting
the following error messages
argument of type const char* is incompatible with parameter of type "LPCWSTR"
err LNK2019:unresolved external symbol_main referenced in function_tmainCRTStartup
Here is the source code
#include<Windows.h>
int _stdcall WinMain(HINSTANCE hinstance,HINSTANCE hPrevinstance,LPSTR lpszCmdline,int nCmdShow)
{
MessageBox(0,"Hello","Title",0);
return(0);
}
Please Help
Thanks and Regards
To compile your code in Visual C++ you need to use Multi-Byte char WinAPI functions instead of Wide char ones.
Set Project -> Properties -> General -> Character Set option to Use Multi-Byte Character Set
I found it here https://stackoverflow.com/a/33001454/5646315
To make your code compile in both modes, enclose the strings in _T() and use the TCHAR equivalents
#include <tchar.h>
#include <windows.h>
int WINAPI _tWinMain(HINSTANCE hinstance, HINSTANCE hPrevinstance, LPTSTR lpszCmdLine, int nCmdShow)
{
MessageBox(0,_T("Hello"),_T("Title"),0);
return 0;
}
I recently ran in to this issue and did some research and thought I would document some of what I found here.
To start, when calling MessageBox(...), you are really just calling a macro (for backwards compatibility reasons) that is calling either MessageBoxA(...) for ANSI encoding or MessageBoxW(...) for Unicode encoding.
So if you are going to pass in an ANSI string with the default compiler setup in Visual Studio, you can call MessageBoxA(...) instead:
#include<Windows.h>
int _stdcall WinMain(HINSTANCE hinstance,HINSTANCE hPrevinstance,LPSTR lpszCmdline,int nCmdShow)
{
MessageBoxA(0,"Hello","Title",0);
return(0);
}
Full documentation for MessageBox(...) is located here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx
And to expand on what #cup said in their answer, you could use the _T() macro and continue to use MessageBox():
#include<tchar.h>
#include<Windows.h>
int _stdcall WinMain(HINSTANCE hinstance,HINSTANCE hPrevinstance,LPSTR lpszCmdline,int nCmdShow)
{
MessageBox(0,_T("Hello"),_T("Title"),0);
return(0);
}
The _T() macro is making the string "character set neutral". You could use this to setup all strings as Unicode by defining the symbol _UNICODE before you build (documentation).
Hope this information will help you and anyone else encountering this issue.
Yes whatever it was it was a wrong tutorial, you need to make it a long byte integer.
Try this:
#include<Windows.h>
int _stdcall WinMain(HINSTANCE hinstance,HINSTANCE hPrevinstance,LPSTR lpszCmdline,int nCmdShow)
{
MessageBox(0,L"Hello",L"Title",0);
return(0);
}

What is the correct type cast to avoid a compiler warning using SERVICE_TABLE_ENTRY from winsvc.h

When trying to set the SERVICE_TABLE_ENTRY using the example at
Creating Windows service without Visual Studio
and compiling using the mingw32 cross-compiler on Fedora 14 I get a compiler warning.
The shortest I can make the sample is
#include <stdio.h>
#include <windows.h>
#include <winsvc.h>
#define MY_SVC_NAME "My Service"
int cont_running = 1;
DWORD WINAPI ServiceHandlerProc(DWORD ControlCode, DWORD a, void *b, void *c)
{
switch (ControlCode)
{
case SERVICE_CONTROL_STOP : ;
cont_running = 0;
}
return 0;
}
void WINAPI ServiceMain(int argc, char *argv[], char *envp[])
{
int hServiceStatus;
hServiceStatus = RegisterServiceCtrlHandlerEx(MY_SVC_NAME, ServiceHandlerProc, 0);
}
int main(int argc, char *argv[], char *envp[])
{
SERVICE_TABLE_ENTRY ServiceStartTable[] =
{
{ MY_SVC_NAME, ServiceMain },
{ 0, 0 }
};
}
but the compiler is complaining about MY_SVC_NAME being the wrong type.
$ /usr/bin/i686-pc-mingw32-gcc -o /tmp/test ~/c/sample.c
sample.c: In function 'main':
sample.c:31:9: warning: initialization from incompatible pointer type
I've tried assigning a variable and using type LPSTR LPWSTR char * and char [] and also tried casting the type within the curly braces, but its not working.
Looking at /usr/i686-pc-mingw32/sys-root/mingw/include/winsvc.h I see its defined as
typedef struct _SERVICE_TABLE_ENTRYA {
LPSTR lpServiceName;
LPSERVICE_MAIN_FUNCTIONA lpServiceProc;
} SERVICE_TABLE_ENTRYA,*LPSERVICE_TABLE_ENTRYA;
typedef struct _SERVICE_TABLE_ENTRYW {
LPWSTR lpServiceName;
LPSERVICE_MAIN_FUNCTIONW lpServiceProc;
} SERVICE_TABLE_ENTRYW,*LPSERVICE_TABLE_ENTRYW;
...
typedef SERVICE_TABLE_ENTRYW SERVICE_TABLE_ENTRY,*LPSERVICE_TABLE_ENTRY;
...
typedef SERVICE_TABLE_ENTRYA SERVICE_TABLE_ENTRY,*LPSERVICE_TABLE_ENTRY;
So surely using
LPSTR my_svc=MY_SVC_NAME;
SERVICE_TABLE_ENTRY ServiceStartTable[] =
{
{ my_svc, ServiceMain },
{ 0, 0 }
};
Should work ???
Sorry, another search revealed this example code at
Windows Service C
I changed my code to
SERVICE_TABLE_ENTRY ServiceStartTable[2];
ServiceStartTable[0].lpServiceName = MY_SVC_NAME;
ServiceStartTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceStartTable[1].lpServiceName = NULL;
ServiceStartTable[1].lpServiceProc = NULL;
and now it compiles without warnings.
This information is from the comments:
typedef void (WINAPI LPSERVICE_MAIN_FUNCTIONA)(DWORD,LPSTR);
typedef void (WINAPI LPSERVICE_MAIN_FUNCTIONW)(DWORD,LPWSTR);
typedef LPSERVICE_MAIN_FUNCTIONA LPSERVICE_MAIN_FUNCTION;
typedef LPSERVICE_MAIN_FUNCTIONW LPSERVICE_MAIN_FUNCTION;
(Presumably only one of the latter two typedefs will be active.)
LPSERVICE_MAIN_FUNCTION is a typedef for a function returning void and taking two arguments of types DWORD and LPSTR or LPWSTR. Your ServiceMain function returns void and takes three arguments of types int, char**, and char**.
Change the definition of ServiceMain function so it's compatible with LPSERVICE_MAIN_FUNCTION.
Casting ServiceMain to LPSERVICE_MAIN_FUNCTION will silence the compiler warning, but it doesn't solve the problem. It will cause your function to be called as if it were declared correctly, with unpredictable results (undefined behavior). All casts should be viewed with suspicion; if your compiler is warning you about a type mismatch, the best solution is usually to change your declarations so the types match, not to force the compiler to pretend that they're ok.
(Is there a typedef that's either LPSTR or LPWSTR, depending on the configuration?)

Resources