Consider a C++ program made of two CPP files, one of which contains a function named "func()" and the other contains main:
void func();
int main(int argc, char *argv[]) {
....
func();
...
}
Note that main does not send argc and argv to func.
Is there any other way by which func can access the command-line arguments? Maybe through some system call?
Related
I'm writing a cross-platform application and need to pass across argc and argv from Objective-C in Xcode to my generic argument handler class in C++. I have a global pointer to this handler class which I set with a new command, but because I can't do new in Objective-C I'm trying the following:
I have a header file called MacCommandLineArgs.h which contains only the following:
static int cmdlArgc = 0;
static const char** cmdlArgv = NULL;
I then set these from within main.m:
int main(int argc, char *argv[])
{
cmdlArgc = argc;
cmdlArgv = (const char**)argv;
return NSApplicationMain(argc, (const char **)argv);
}
Once the Objective-C++ section of the application has been entered, I try to read back these global variables in order to pass them to the pure-C++ class:
int argc = cmdlArgc;
const char** argv = cmdlArgv;
globalCommandLineArgs = new CCommandLineArgs(argc, argv);
When stepping through with the debugger, cmdlArgc and cmdlArgv show up as valid data but argc and argv are still 0 and NULL after the assignment. What am I doing wrong here?
You don't show how cmdlArgc and cmdlArgv are declared; it's surely in a header file, but what does it look like?.
Nothing outside of main.m will have access to those variables as they have been defined static, which leads me to wonder why you aren't getting linker errors. I have concluded that the declaration of the of cmdlArgc and cmdArgv is something like this:
int cmdlArgc;
const char** cmdlArgv;
rather than this:
extern int cmdlArgc;
extern const char** cmdlArgv;
So every implementation file that includes the header will get their own copy, which is why it's 0/NULL.
The solution is to drop the use of static in main.m and start using extern in the header.
However it's still an ugly pattern and I would think the very best solution is to rename main.m to main.mm and initialise CCommandLineArgs in main(), which is both clean and simple.
So I am writing a wrapper for main and still provide a main like functionality, so user can define int main() or int main(argc, argv) and both works fine. I am able to do that for some compilers with inline assembly with pushing argc & argv onto stack before calling the user's main. However for x64 VC++, there is no inline assembly, so any suggestions on how I can achieve this?
Thanks!
I see two obvious choices: either write your code in assembly language, contained in an assembly language file, or else write your code in C++ without any inline assembly:
void my_entry_point() {
int argc = foo();
int argv = bar();
int ret = main(argc, argv);
exit_to_os(ret);
}
I'm trying to figure out why this is not working. I want to do like in Java where main is a static function in a class but this is producing unresolved external symbol error:
static class MainClass
{
public:
static int _tmain(int argc, char* argv[])
{
return 0;
}
};
Why doesn't this work?
Thanks
C++ does not work like that.
You need main as a function:
int main(int argc,char* argv[])
{
//STUFF
}
Because _tmain is mangled in the binary with the class name MainClass in it, so multiple classes could have a function _tmain in them and not conflict. It's not got the same mangled name as ::_tmain is going to have.
I remember that with an earlier version of MSVC, it accepted the following without a linker error which ended up accidentally as a result of macro expansion in my code base once
namespace bar {
int main() { }
}
It apparently treated the name main specially and didn't mangle it or mangle it the same as ::main. But such a thing is not Standard conformant. Like in the class case, such a function is completely unrelated to the main function.
_tmain is called from CRT. You need to set in your linker an entry point to another function that will call MainClass::_tmain instead.
Because, in C++, you cannot put an entry point inside a class. This answer might help.
Why doesn't that work? Because it's not C++.
struct MainClass {
static int main(int argc, char** argv) {
return 0;
}
};
int main(int argc, char** argv) {
return MainClass::main(argc, argv);
}
It's not really C++, so much as the standard linker process which is looking for an export of a specific name (with C-style linkage). The specific export varies based on the compiler and executable type, but the format is specific for each type. For example, Windows GUI exe's have different entry points than console, and specific for ASCII or UNICODE. But the linker is always looking for a function with a specific link name, which is why a static member won't work.
You always need main() defined as a global function. This is where the program always starts in C++. You could simple call your static class function from main and pass on the variables if you really want to:
class MainClass
{
public:
static int _tmain(int argc, char* argv[])
{
return 0;
}
};
int main(int argc, char* argv[]) {
return MainClass::_tmain(argc, argv);
}
if i got a c++ executable file like this: executable.exe and i want to add some parameters like:
executable.exe +username = pino
how do i get in c++ that i filled in pino as my username?
Arguments to main. Your main is
int main(int argc, char **argv) {
...
}
All the command-line params are in argv. There are also Windows-specific APIs.
In Visual Studio 2003 using pure C, old-style function
declarations do not show as global member
i.e. void func(blah) int blah;{...}
This shows as a global member in the members dropdown:
void func(int blah)
{
...
}
This compiles, but old-style does not appear in the global
members dropdown:
void func(blah)
int blah;
{
...
}
I am trying to use the new 'Calling Graph' functionality to
analyse code, but as most of our legacy code uses the
old-style function parameters, those functions are not
recognized are not shown as Global Members, and therefore do
not appear in the 'Calling Graph'.
Is there any way to let the "call graph" analysis process
old-style function declarations correctly?
Maybe you want to consider to just change the old style function signatures. There shouldn't be any issues with that.
EDIT:
For an automatic conversion of your source files from old style syntax to ANSI-C style, take a look at the cproto tool. Maybe that could save you some time if you decide to go that direction.
This is an excerpt from the docs:
-f n
Set the style of generated function prototypes where n is a
number from 0 to 3. For example,
consider the function definition
main (argc, argv)
int argc;
char *argv[];
{
}
If the value is 0, then no prototypes are generated. When set to
1, the output is:
int main(/*int argc, char *argv[]*/);
For a value of 2, the output has the form:
int main(int /*argc*/, char */*argv*/[]);
The default value is 3. It produces the full function prototype:
int main(int argc, char *argv[]);
I'm not sure but maybe the engine uses regexs to trace routine signatures and the old C style isn't implemented.