Is main() a pre-defined function in C? [duplicate] - c

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
main() in C, C++, Java, C#
I'm new to programming in general, and C in particular. Every example I've looked at has a "main" function - is this pre-defined in some way, such that the name takes on a special meaning to the compiler or runtime... or is it merely a common idiom among C programmers (like using "foo" and "bar" for arbitrary variable names).

No, you need to define main in your program. Since it's called from the run-time, however, the interface your main must provide is pre-defined (must return an int, must take either zero arguments or two, the first an int, and the second a char ** or, equivalently, char *[]). The C and C++ standards do specify that a function with external linkage named main acts as the entry point for a program1.
At least as the term is normally used, a predefined function would be one such as sin or printf that's in the standard library so you can use it without having to write it yourself.
1If you want to get technical, that's only true for a "hosted" implementation -- i.e., the kind most of us use most of the time that produces programs that run on an operating system. A "free-standing" implementation (one produces program that run directly on the "bare metal" with no operating system under it) is free to define the entry point(s) as it sees fit. A free-standing implementation can also leave out most of the normal run-time library, providing only a handful of headers (e.g., <stddef.h>) and virtually no standard library functions.

Yes, main is a predefined function in the general sense of the the word "defined". In other words, the C language standard specifies that the function called at program startup shall be named main. It is not merely a convention used by programmers as we have with foo or bar.
The fine print: from the perspective of the technical meaning of the word "defined" in the context of C programming, no the main function is not "predefined" -- the compiler or C library do not supply a predefined function named main. You need to define your own implementation of the main function (and, obviously, you should name it main).

There is typically a piece of code that normal C programs are linked to which does:
extern int main(int argc, char * argv[], char * envp[]);
FILE * stdin;
FILE * stdout;
FILE * stderr;
/* ** setup argv ** */
...
/* ** setup envp ** */
...
/* ** setup stdio ** */
stdin = fdopen(0, "r");
stdout = fdopen(1, "w");
stderr = fdopen(2, "w");
int rc;
rc = main(argc, argv, envp); // envp may not be present here with some systems
exit(rc);
Note that this code is C, not C++, so it expects main to be a C function.
Also note that my code does no error checking and leaves out a lot of other system dependent stuff that probably happens. It also ignores some things that happen with C++, objective C, and various other languages that may be linked to it (notably constructor and destructor calling, and possibly having main be within a C++ try/catch block).
Anyway, this code knows that main is a function and takes arguments. If your main looks like:
int main(void) {
Then it still gets passed arguments, but they are ignored.
This code specially linked so that it is called when the program starts up.
You are completely free to write your own version of this code on many architectures, but it relies on intimate knowledge of how the operating system starts a new program as well as the C (and C++ and possibly Objective C) run time. It is likely to require some assembly programming and or use of compiler extensions to properly build.
The C compiler driver (the command you usually call when you call the compiler) passes the object file containing all of this (often called crt0.0, for C Run Time ...) along with the rest of your program to the linker, unless told not to.
When building an operating system kernel or an embedded program you often do not want to use the standard crt*.o file. You also may not want to use it if you are building a normal application in another programming language, or have some other non-standard requirements.

No, or you couldn't define one.
It's not predefined, but its meaning as an entry point, if it is present, is defined.

Related

How were C's different signatures for main supported before _Generic?

_Generic became available with C11, and before that in C99, tgmath.h included similar functionality using compiler specific hacks.
but how did main have multiple signatures back in K&R C, or C89/C90?
there's at least 2 function signatures for main() that I'm aware of:
1: int main(int argc, const char *argv[]);
2: int main(void);
but how did main have multiple signatures back in K&R C, or C89/C90?
main did not have multiple signatures per se in K&R C. That version had no sense of "signature" as you mean it. Although functions did have expectations about the number and types of their arguments, and their behavior was defined only if those expectations were satisfied, function arguments did not constitute a part of function declarations.
The following quotation from section 5.11 of the first edition of The C Programming Language (Kernighan & Ritchie, 1978) may be illuminating:
When main is called to begin execution, it is called with two arguments.
The statement is unconditional: main is (always) called with two arguments in C as described by K&R. Compilers could do whatever they wanted or needed to deal with cases where those parameters were not declared.
The case is not really different in C90 or any later version of C (all of which still support K&R-style functions definitions). Even when main is declared with a prototype, implementations do whatever they want or need to do. For example, maybe they generate code for a standard signature, and perform any necessary patch-up of recursive calls to main() during linking. Or maybe they generate code for whatever (supported) declaration of main() is provided, and deal with it in some kind of OS-specific wrapper. Maybe nothing special is even needed in some implementations.
The C Standard only requires the implementation to support the two signatures given in the question,
1: int main(int argc, const char *argv[]);
2: int main(void);
For calling conventions where the caller pops the arguments off the calling stack, the calling sequence for (1) works fine for (2) -- the caller pushes the arguments onto the stack, the callee (main) never uses them, and the caller removes them from the stack.
For calling conventions where the callee pops the arguments off the calling stack, main would have to be compiled differently depending on which signature is used. This would be a problem in implementations with a fixed piece of startup code in the C runtime, since it doesn't know how main was declared. The easiest way to deal with that is to always use a "caller pops" calling convention for main, and this is in fact how Microsoft's C compiler works -- see, e.g., https://learn.microsoft.com/en-us/cpp/build/reference/gd-gr-gv-gz-calling-convention, which states that other calling conventions are ignored when applied to main.
P.S.
_Generic and tgmath.h had no effect on any of this.
There were no signatures in K&R C, only the names of the arguments and optional type declarations for them, so there was only one possible calling convention for main.
So, none of these language changes over the decades has had any effect on how main is called.
C had and has no munged function signatures. Certainly nothing parameter-specific. Most compilers prepended (and some appended) an underscore ("_") to create a poor-man's linker namespace which made it easy to prevent symbol name collisions.
So the C runtime startup would always have one unambiguous symbol to startup. Most often _main.
start:
;# set up registers
;# set up runtime environment:
;# set up stack, initialize heap, connect stdin, stdout, stderr, etc.
;# obtain environment and format for use with "envp"
;# obtain command line arguments and set up for access with "argv"
push envp
push argv
push argc ; number of arguments in argv
call _main
push r0
call exit
.end start

Why can C main function be coded with or without parameters?

Just wondering why this
int main(void){}
compiles and links
and so does this:
int main(int argc, char **argv){}
Why isn't it required to be one or the other?
gcc will even compile and link with one argument:
int main(int argc){}
but issue this warning with -Wall:
smallest_1.5.c:3:1: warning: ‘main’ takes only zero or two arguments [-Wmain]
I am not asking this as in "how come they allow this?" but as in "how does the caller and the linker handle multiple possibilities for main?"
I am taking a Linux point of view below.
The main function is very special in the standard definition (for hosted C11 implementations). It is also explicitly known by recent compilers (both GCC & Clang/LLVM....) which have specific code to handle main (and to give you this warning). BTW, GCC (with help from GNU libc headers thru function attributes) has also special code for printf. And you could add your own customization to GCC using MELT for your own function attributes.
For the linker, main is often a usual symbol, but it is called from crt0 (compile your code using gcc -v to understand what that really means). BTW, the ld(1) linker (and ELF files, e.g. executables or object files) has no notion of types or function signatures and deals only with names (This is why C++ compilers do some name mangling).
And the ABI and the calling conventions are so defined that passing unused arguments to a function (like main or even open(2)...) does not do any harm (several arguments get passed in registers). Read the x86-64 System V ABI for details.
See also the references in this answer.
At last, you really should practically define your main as int main(int argc, char**argv) and nothing else, and you hopefully should handle program arguments thru them (at least --help & --version as mandated by GNU coding standards). On Linux, I hate programs (and I curse their programmers) not doing that (so please handle --help & --version).
Because the calling code can, for example, pass arguments in registers or on the stack. The two argument main uses them, while the zero argument main does nothing with them. It's that simple. Linking does not even enter the picture.
If you are worried about stack adjustments in the called code, the main function just needs to make sure the stack pointer is the same when it returns (and often even this is of no importance, e.g. when the ABI states that the caller is responsible for stack management).
Making it work has to do with the binary format of the executable and the OS's loader. The linker doesn't care (well it cares a little: it needs to mark the entry point) and the only caller routine is the loader.
The loader for any system must know how to bring supported binary format into memory and branch into the entry point. This varies slightly by system and binary format.
If you have a question about a particular OS/binary format, you may want to clarify.
The short answer: if you don't use the parameters, then you can declare main without parameters, in two ways:
int main(void)
or
int main()
The first means main is a function with no parameters. The second means main is a function with any number of parameters.
Since you don't access the parameters, both will be fine. Any compiler having "special" code to check the parameters of main is wrong. (But: main must return a value.)
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent; or in some other implementation-defined manner.
Regarding the parameters:
The first counts the arguments supplied to the program and the second is an array of pointers to the strings which are those arguments. These arguments are passed to the program by the command line interpreter.
So, the two possibilities are handled as:
If no parameters are declared: no parameters are expected as input.
If there are parameters in main() ,they should:
argc is greater than zero.
argv[argc] is a null pointer.
argv[0] through to argv[argc-1] are pointers to strings whose meaning will be determined by the program.
argv[0] will be a string containing the program's name or a null string if that is not available. Remaining elements of argv represent the arguments supplied to the program. In cases where there is only support for single-case characters, the contents of these strings will be supplied to the program in lower-case.
In memory:
they will be placed on the stack just above the return address and the saved base pointer (just as any other stack frame).
At machine level:
they will be passed in registers, depending on the implementation.

Why all c programs should start with a main() that returns a `int`? [duplicate]

This question already has answers here:
What should main() return in C and C++?
(19 answers)
Closed 8 years ago.
I like to know what is the main reason that all C programs should start with the standard function of "int main()"? and why it should be "int" ? Thank you
Not all C "programs" start with "int main." I put program in quotes to highlight the fact that you can have c files that do not have main in them, such as class definitions. Essentially main is the section of code that tells the computer what to do, and in what order -- all other files can be thought of as helper files that partition the code to make it more readable and maintainable. Main has an int type because the program will return an integer value describing if the program executed without a problem, which corresponds to a return of 0, or what went wrong, which can be any non-zero number that usually has documentation that will tell you what the corresponding number meant in terms of failure.
When you execute a program, the first thing to run is initialization code in the C library. When it finishes, it calls the standard entry point, main, with the parsed command line arguments. The int return value from main is the return value of the program.
Actually, not all C programs have to have a main. The ISO C standard supports two types of environments. The first is hosted, and that is the one that requires a main of a specific format (from several allowable ones).
Freestanding environments (the second type) have no such requirement and, in fact, there's a lot of leeway for freestanding behaviour at many other points in the standard as well.
That's why you can still consider the Linux kernel to be a C program despite the fact there's not a main in sight.
As to why hosted environments have this requirement, that's the way C was originally written back in the 70s and, when ANSI came to do the standard, their primary brief was to codify existing practice, not create a new language.
The long chain of standards committees following that, ISO C89/90, C99 and C11 have either not been convinced that there was any need to change it, or their contributors have not put forward the idea.
A program has to start running somewhere; this is called its "entry point". The standard entry point for a C program is called "main" because that's what someone chose long ago and there's no real reason to change it to some other name. However, some compilers (actually, linkers) have options to build a program using some other function name as the entry point.
The main function returns an int to provide feedback about whether it ran successfully. By convention, returning 0 indicates that the program succeeded, and returning some other value indicates that it failed. You can check this result with, for example, the $? environment variable in the bash shell.
This is because of the fact how your code is to be called and the Standard says how it should happen. As to the return value, there is a rule that says that main function has to return the integer as a result of a call to the caller - it should indicate how the program exited.
Why all c programs should start with int main ()?
This is because:
When the operating system runs a program in C, it passes control of the computer over to that program. This is like the captain of a huge ocean liner handing you the wheel. Aside from any fears that may induce, the key point is that the operating system needs to know where inside your program the control needs to be passed. In the case of a C language program, it's the main() function that the operating system is looking for.
and why it should be "int" ?
5.1.2.2.1 Program startup:
The function called at program startup is named main. The implementation declares no
prototype for this function. It shall be defined with a return type of int [...]
it is a matter of standard, check out ansi C standard it states that main function should return int value. Also from operating system point of view returning value from main function is only indicator if program ended properly.

In C, given a variable list of arguments, how to build a function call using them?

Suppose there's a list of arguments stored somehow, in a array for example.
Given a function pointer, how could I make a call to it passing the stored list of arguments?
I'm not trying to pass the array as an argument ok. You got it, ok? I want to pass each of its elements as an argument. An array is just to illustrate, I could be storing the arguments in some tuple structure. Also, look that I have at hand a function pointer and may have a signature in string format. I'm not trying to just define a function that is able to deal with a variadic list.
The only way I see how to do that is by employing assembly (by __asm push et al.) or this:
void (*f)(...);
int main()
{
f = <some function pointer>;
int args[]; <stored in a array, just to illustrate>
int num_args = <some value>;
switch(num_args)
{
case 0:
f();
break;
case 1:
f(args[0]);
break;
case 2:
f(args[0], args[1]);
break;
/* etc */
}
return 0;
}
I don't like this approach too much...
Is there another portable and shorter form?
Several script languages are able to call C functions.
How script languages like Python or Ruby do that? How they implement it in a portable way? Does they just use assembly for several platforms or the above in the end?
Look that I'm really not asking about details of parameter marshaling and other stuff from script languages to C, I'm interested only in how, in the end, internally, the call to the C function by the script language is built.
EDIT
I'll keep the question's title but I think a better way for asking it is:
How to call a C function with its pointer and signature available only at runtime?
UPDATE
From Foreign Interface for PLT Scheme:
A call-out is a normal function call. In a dynamic setting,
we create a “call-interface” object which specifies (binary)
input/output types; this object can be used with an arbitrary
function pointer and an array of input values to perform a callout to the function and retrieve its result. Doing this requires
manipulating the stack and knowing how a function is called,
these are details that libffi deals with.
Thanks #AnttiHaapala for searching, finding and pointing libffi. It's what I was looking for, it's being used by a bunch of script languages, it's a portable library, implemented across several architectures and compilers.
You asked what is the portable way to call any function pointer with given number of arguments. The correct answer is that there is no such way.
For example python is able to call C functions through the ctypes module, but this is portable only for as long as you know the exact prototype and calling conventions. In C the easiest way to achieve the same is to know the prototype of the function pointer at compile time.
Update
For python / ctypes example, on each platform that has the ctypes module enabled, python knows how to write the calling stack for a given set of arguments. On Windows for example, python knows of 2 standard calling conventions - cdecl with C order of parameters on stack, and stdcall with "pascal style ordering". On Linux it does need to worry about whether to call 32 or 64 bit shared objects, and so forth. If python is compiled to another platform, the ctypes needs changes as well; the C code in ctypes module is not, as such, portable.
Update 2
For Python the magic is in here: ctypes source code. Notably it seems to link http://sourceware.org/libffi/ which might be just what you needed.
I am the author of libffi. It will do what you are asking.
#AnttiHaapala pointed out libffi. Here's some information about it:
What is libffi?
Some programs may not know at the time of compilation what arguments are to be passed to a function. For instance, an interpreter may be told at run-time about the number and types of arguments used to call a given function. ‘libffi’ can be used in such programs to provide a bridge from the interpreter program to compiled code.
The ‘libffi’ library provides a portable, high level programming interface to various calling conventions. This allows a programmer to call any function specified by a call interface description at run time.
FFI stands for Foreign Function Interface. A foreign function interface is the popular name for the interface that allows code written in one language to call code written in another language. The ‘libffi’ library really only provides the lowest, machine dependent layer of a fully featured foreign function interface. A layer must exist above ‘libffi’ that handles type conversions for values passed between the two languages.
‘libffi’ assumes that you have a pointer to the function you wish to call and that you know the number and types of arguments to pass it, as well as the return type of the function.
Historic background
libffi, originally developed by Anthony Green (SO user: anthony-green), was inspired by the Gencall library from Silicon Graphics. Gencall was developed by Gianni Mariani, then employed by SGI, for the purpose of allowing calls to functions by address and creating a call frame for the particular calling convention. Anthony Green refined the idea and extended it to other architectures and calling conventions and open sourcing libffi.
Calling pow with libffi
#include <stdio.h>
#include <math.h>
#include <ffi.h>
int main()
{
ffi_cif call_interface;
ffi_type *ret_type;
ffi_type *arg_types[2];
/* pow signature */
ret_type = &ffi_type_double;
arg_types[0] = &ffi_type_double;
arg_types[1] = &ffi_type_double;
/* prepare pow function call interface */
if (ffi_prep_cif(&call_interface, FFI_DEFAULT_ABI, 2, ret_type, arg_types) == FFI_OK)
{
void *arg_values[2];
double x, y, z;
/* z stores the return */
z = 0;
/* arg_values elements point to actual arguments */
arg_values[0] = &x;
arg_values[1] = &y;
x = 2;
y = 3;
/* call pow */
ffi_call(&call_interface, FFI_FN(pow), &z, arg_values);
/* 2^3=8 */
printf("%.0f^%.0f=%.0f\n", x, y, z);
}
return 0;
}
I think I can assert libffi is a portable way to do what I asked, contrary to Antti Haapala's assertion that there isn't such a way. If we can't call libffi a portable technology, given how far it's ported/implemented across compilers and architectures, and which interface complies with C standard, we too can't call C, or anything, portable.
Information and history extracted from:
https://github.com/atgreen/libffi/blob/master/doc/libffi.info
http://en.wikipedia.org/wiki/Libffi
For safety you should unpack the variables before they are sent. Using assembler to hack the parameter stack might not be portable between compilers. Calling conventions might vary.
I can't speak for Ruby, but I have written quite a few programs using the C interfaces to Perl and Python. Perl and Python variables are not directly comparible with C variables, they have many more features. For example, a Perl scalar might have dual string and numeric values, only one of which is valid at any one time.
Conversion between Perl/Python variables and C is done using pack and unpack (in the struct module in Python). At the C interface you have to call specific APIs to do the conversion, depending on type. So, it is not just a straight pointer transfer, and it certainly does not involve assembler.

Avoiding the main (entry point) in a C program

Is it possible to avoid the entry point (main) in a C program. In the below code, is it possible to invoke the func() call without calling via main() in the below program ? If Yes, how to do it and when would it be required and why is such a provision given ?
int func(void)
{
printf("This is func \n");
return 0;
}
int main(void)
{
printf("This is main \n");
return 0;
}
If you're using gcc, I found a thread that said you can use the -e command-line parameter to specify a different entry point; so you could use func as your entry point, which would leave main unused.
Note that this doesn't actually let you call another routine instead of main. Instead, it lets you call another routine instead of _start, which is the libc startup routine -- it does some setup and then it calls main. So if you do this, you'll lose some of the initialization code that's built into your runtime library, which might include things like parsing command-line arguments. Read up on this parameter before using it.
If you're using another compiler, there may or may not be a parameter for this.
When building embedded systems firmware to run directly from ROM, I often will avoid naming the entry point main() to emphasize to a code reviewer the special nature of the code. In these cases, I am supplying a customized version of the C runtime startup module, so it is easy to replace its call to main() with another name such as BootLoader().
I (or my vendor) almost always have to customize the C runtime startup in these systems because it isn't unusual for the RAM to require initialization code for it to begin operating correctly. For instance, typical DRAM chips require a surprising amount of configuration of their controlling hardware, and often require a substantial (thousands of bus clock cycles) delay before they are useful. Until that is complete, there may not even be a place to put the call stack so the startup code may not be able to call any functions. Even if the RAM devices are operational at power on, there is almost always some amount of chip select hardware or an FPGA or two that requires initialization before it is safe to let the C runtime start its initialization.
When a program written in C loads and starts, some component is responsible for making the environment in which main() is called exist. In Unix, linux, Windows, and other interactive environments, much of that effort is a natural consequence of the OS component that loads the program. However, even in these environments there is some amount of initialization work to do before main() can be called. If the code is really C++, then there can be a substantial amount of work that includes calling the constructors for all global object instances.
The details of all of this are handled by the linker and its configuration and control files. The linker ld(1) has a very elaborate control file that tells it exactly what segments to include in the output, at what addresses, and in what order. Finding the linker control file you are implicitly using for your toolchain and reading it can be instructive, as can the reference manual for the linker itself and the ABI standard your executables must follow in order to run.
Edit: To more directly answer the question as asked in a more common context: "Can you call foo instead of main?" The answer is "Maybe, but but only by being tricky".
On Windows, an executable and a DLL are very nearly the same format of file. It is possible to write a program that loads an arbitrary DLL named at runtime, and locates an arbitrary function within it, and calls it. One such program actually ships as part of a standard Windows distribution: rundll32.exe.
Since a .EXE file can be loaded and inspected by the same APIs that handle .DLL files, in principle if the .EXE has an EXPORTS section that names the function foo, then a similar utility could be written to load and invoke it. You don't need to do anything special with main, of course, since that will be the natural entry point. Of course, the C runtime that was initialized in your utility might not be the same C runtime that was linked with your executable. (Google for "DLL Hell" for hint.) In that case, your utility might need to be smarter. For instance, it could act as a debugger, load the EXE with a break point at main, run to that break point, then change the PC to point at or into foo and continue from there.
Some kind of similar trickery might be possible on Linux since .so files are also similar in some respects to true executables. Certainly, the approach of acting like a debugger could be made to work.
A rule of thumb would be that the loader supplied by the system would always run main. With sufficient authority and competence you could theoretically write a different loader that did something else.
Rename main to be func and func to be main and call func from name.
If you have access to the source, you can do this and it's easy.
If you are using an open source compiler such as GCC or a compiler targeted at embedded systems you can modify the C runtime startup (CRT) to start at any entry point you need. In GCC this code is in crt0.s. Generally this code is partially or wholly in assembler, for most embedded systems compilers example or default start-up code will be provided.
However a simpler approach is to simply 'hide' main() in a static library that you link to your code. If that implementation of main() looks like:
int main(void)
{
func() ;
}
Then it will look to all intents and purposes as if the user entry point is func(). This is how many application frameworks with entry points other than main() work. Note that because it is in a static library, any user definition of main() will override that static library version.
The solution depends on the compiler and linker which you use. Always is that not main is the real entry point of the application. The real entry point makes some initializations and call for example main. If you write programs for Windows using Visual Studio, you can use /ENTRY switch of the linker to overwrite the default entry point mainCRTStartup and call func() instead of main():
#ifdef NDEBUG
void mainCRTStartup()
{
ExitProcess (func());
}
#endif
If is a standard practice if you write the most small application. In the case you will receive restrictions in the usage of C-Runtime functions. You should use Windows API function instead of C-Runtime function. For example instead of printf("This is func \n") you should use OutputString(TEXT("This is func \n")) where OutputString are implemented only with respect of WriteFile or WriteConsole:
static HANDLE g_hStdOutput = INVALID_HANDLE_VALUE;
static BOOL g_bConsoleOutput = TRUE;
BOOL InitializeStdOutput()
{
g_hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
if (g_hStdOutput == INVALID_HANDLE_VALUE)
return FALSE;
g_bConsoleOutput = (GetFileType (g_hStdOutput) & ~FILE_TYPE_REMOTE) != FILE_TYPE_DISK;
#ifdef UNICODE
if (!g_bConsoleOutput && GetFileSize (g_hStdOutput, NULL) == 0) {
DWORD n;
WriteFile (g_hStdOutput, "\xFF\xFE", 2, &n, NULL);
}
#endif
return TRUE;
}
void Output (LPCTSTR pszString, UINT uStringLength)
{
DWORD n;
if (g_bConsoleOutput) {
#ifdef UNICODE
WriteConsole (g_hStdOutput, pszString, uStringLength, &n, NULL);
#else
CHAR szOemString[MAX_PATH];
CharToOem (pszString, szOemString);
WriteConsole (g_hStdOutput, szOemString, uStringLength, &n, NULL);
#endif
}
else
#ifdef UNICODE
WriteFile (g_hStdOutput, pszString, uStringLength * sizeof (TCHAR), &n, NULL);
#else
{
//PSTR pszOemString = _alloca ((uStringLength + sizeof(DWORD)));
CHAR szOemString[MAX_PATH];
CharToOem (pszString, szOemString);
WriteFile (g_hStdOutput, szOemString, uStringLength, &n, NULL);
}
#endif
}
void OutputString (LPCTSTR pszString)
{
Output (pszString, lstrlen (pszString));
}
This really depends how you are invoking the binary, and is going to be reasonably platform and environment specific. The most obvious answer is to simply rename the "main" symbol to something else and call "func" "main", but I suspect that's not what you are trying to do.

Resources