static main from static class? - c++

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);
}

Related

Accessing command-line arguments from within a c++ program

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?

Objective-C variables read as null in C++

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.

static variable declaration and definition in C++

I have a sample code as shown below:
class myclass
{
public:
static int j;
myclass(){};
~myclass(){};
};
int main(int argc, char** argv) {
myclass obj;
return EXIT_SUCCESS;
}
Now I have declared a static int inside myclass and although I have not defined it, the compiler does not give me any errors until I began using the static variable. Why is that?
Because these are linker errors, not compiler errors. Linker errors never arise until you use an undefined symbol.
"the compiler does not give me any errors until I began using the static variable. Why is that?"
Because it didn't need to be linked with your code until that point (when you start to use it). Unused code is ignored / stripped off by the linker.

Is this use of global static initialization okay for a "busybox" style application?

Still working on my closed/open source hybrid talked about earlier in this question. The application in question is actually a busybox like application -- there are several programs bundled into a single program, and the actual program run is chosen based upon the first command entered. This allows the sub-programs to share one copy of the CRT (I can't use the installable redist because I need to maintain single binary deployment), as well as several internals which are useful in several of the sub programs.
Because some of the sub programs themselves cannot be released as a result of licensing restrictions, I'm considering using a startup like this. (Sorry for the amount of code :( )
ISubProgram.hpp
#include <string>
struct ISubProgram
{
virtual std::wstring GetExecutive() const = 0; //Return sub program name
virtual void OnStart(int argc, const char *argv[]) {};
virtual int Run(int argc, const char *argv[]) = 0;
virtual ~ISubProgram() {}
};
SubProgramList.hpp
#include <memory>
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/noncopyable.hpp>
#include "ISubProgram.hpp"
class SubProgramList;
SubProgramList& GetSubProgramList();
class SubProgramList : boost::noncopyable
{
friend SubProgramList& GetSubProgramList();
SubProgramList() {} //Disallow direct creation.
boost::ptr_map<std::wstring,ISubProgram> programs;
public:
void RegisterProgram(std::auto_ptr<ISubProgram> subProgramToRegister);
ISubProgram * FindProgramFromExecutive(const std::wstring& executive);
void CallOnStartMethods(int argc, char *argv[]);
};
template <typename T>
struct RegisterSubProgram
{
RegisterSubProgram()
{
std::auto_ptr<ISubProgram> toAdd(new T);
GetSubProgramList().RegisterProgram(toAdd);
}
}
SubProgramList.cpp
SubProgramList& GetSubProgramList()
{
static SubProgramList theList;
return theList;
}
//Implementations of the class methods
ExampleSubProgram.cpp
#include "SubProgramList.hpp"
struct ExampleSubProgram : public ISubProgram
{
virtual std::wstring GetExecutive()
{
return L"ExampleSubProgram";
}
virtual int Run(int argc, const char *argv[])
{
//Run this program :)
}
};
namespace { RegisterSubProgram<ExampleSubProgram> registrar; }
Main.cpp
#include "SubProgramList.hpp"
int main(int argc, char *argv[])
{
SubProgramList& list = GetSubProgramList();
list.CallOnStartMethods(argc, argv);
std::wstring subProgramName(/*.. Generate from argv[1] ...*/);
FindProgramFromExecutive(subProgramName)->Run(argc, argv);
}
I think I'm clear of initialization order issues because the only global state is a local static rather than a global static.
The main reason for this is that I can completely pull apart the closed source and open source bits of the program, which would make merging quick and efficient, and also removes the boilerplate of my current "Giant if/else subprogram selector" in main.
Is this a reasonable use of on-start initialization (which is generally discouraged?) If not, what alternate implementation would you suggest?
I could come up with some clever programs with recursive template instantiation, but the reality is that what you've done is probably simpler than what I can come up with. It's rare that I suggest that global state is a smart idea, but on this one I may have to accept that I can't do better.

VC++: non-global old-style function declarations?

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.