I have some code here to call minizip(), a boilerplate dirty renamed main() of the minizip program, but when I compile, I get *undefined reference to `minizip(int, char**)*. Here's the code.
int minizip(int argc, char* argv[]);
void zipFiles(void)
{
char arg0[] = "BBG";
char arg1[] = "-0";
char arg2[] = "out.zip";
char arg3[] = "server.cs";
char* argv[] = {&arg0[0], &arg1[0], &arg2[0], &arg3[0], 0};
int argc = (int)(sizeof(argv) / sizeof(argv[0])) - 1;
minizip(argc, argv);
}
int minizip(argc,argv)
int argc;
char *argv[];
{
...
}
Is all of that code in the same file? If not, and if the caller is C++ code and minizip is C code, the caller might need the minizip declaration within an extern "C" block to indicate that it will be calling a C function and therefore will need C linkage.
(Also, don't retype error messages. Copy and paste them so that they are exact. In this case, the compiler most likely reported an undefined reference to minizip(int, char**).)
Why are you declaring the function arguments again in:
int minizip(argc,argv)
int argc;
char *argv[];
{
...
}
It' should say
int minizip(int argc,char *argv[])
{
...
}
Related
#include <iostream>
using namespace std;
defining class
class fancyString {
private:
char *content;
bool flag_bold;
bool flag_italics;
public:
fancyString(){
content="";
flag_bold= false;
flag_italics=false;
}
in both functions I'm asked to use the old fashioned calloc
fancyString(char* cntnt){
content=(char *) calloc(strlen(cntnt)+1, sizeof(char*));
Usually the strcpy is the main reason of the crash
strcpy(cntnt,content);
}
fancyString(fancyString & f1){
content=(char *) calloc(strlen(f1.content)+1, sizeof(char*));
Usually the strcpy is the main reason of the crash
strcpy(f1.content,content);
flag_bold=f1.flag_bold;
flag_italics=f1.flag_italics;
}
friend ostream& operator<<(ostream& os, const fancyString& FS){
os<<"string is "<<FS.content<<endl<<"bold status is "<<FS.flag_bold<<endl<<"italics status is "<<FS.flag_italics<<endl;
return os;
}
~fancyString(){
cout << "Destroying the string\n";
if ( content != NULL )
free (content);
}
};
main function
int main(int argc, const char * argv[]) {
fancyString fs1 ("First Example");
fancyString fs2(fs1);
cout<<fs2;
return 0;
}
You have the arguments to the strcpy calls the wrong way round! See the definition on cppreference:
char * strcpy ( char * destination, const char * source );
So, in your your first constructor, the call:
strcpy(cntnt,content);
is attempting to copy the newly-allocated buffer into the passed argument, which is actually a (constant) string literal:
int main(int argc, const char * argv[]) {
fancyString fs1 ("First Example");
//...
NOTES based on suggestions made in the comments:
(1) Note that, in your calloc call - which is allocating an 'array' of char, the elements' size is sizeof(char) not sizeof(char*) (which would be appropriate for an 'array' of pointers). Use:
content = (char *) calloc(strlen(cntnt)+1, sizeof(char));
and similarly in the copy constructor.
(2) Assuming that your first constructor is never intended to modify the string given as its argument, you should really specify it as const:
fancyString(const char* cntnt){
//...
(This would have flagged the error of having the strcpy arguments wrong!)
Please feel free to ask for further clarification and/or explanation.
Is it possible to get the command line arguments without receiving them via int main(int, char**)? I don't want to pass the arguments to multiple methods, so a global function would be perfect. Also, I do not want to store the arguments by myself via global variables. I'm running Windows and Linux.
edit:
Example:
int main()
{
int argc = GetArgumentCount();
char ** argv = GetArguments();
return 0;
}
edit:
It's possible to use LPTSTR WINAPI GetCommandLine(void); in win32.
https://msdn.microsoft.com/en-us/library/ms683156(v=vs.85).aspx
I'm looking for equivalent functions in Linux.
Is it possible to get the command line arguments without receiving
them via int main(int, char**)?
Yes, with platform-specific functions. But that's not necessary (see below).
I don't want to pass the arguments to multiple methods,
That's understandable. It's an anti-pattern also known as "tramp data".
Also, I do not want to store the arguments by myself via global variables.
Yes, global variables are rarely a good idea.
Here's an alternative approach: store them as a static local container object in some globally available non-member function which returns the container by reference.
Example:
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string>& Arguments()
{
static std::vector<std::string> arguments;
return arguments;
}
void f()
{
// use arguments anywhere else:
std::cout << Arguments()[0];
}
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
Arguments().push_back(argv[i]);
}
f();
}
Of course, this can be made more sophisticated. For example, you might want to prevent anyone else but main from changing the vector by wrapping the vector in a class and declaring main as a friend, something like this:
#include <iostream>
#include <string>
#include <vector>
class Arguments final
{
public:
static int Count()
{
return arguments.size();
}
static std::string Get(int index)
{
return arguments[index];
};
private:
Arguments() = delete;
friend int main(int argc, char* argv[]);
static std::vector<std::string> arguments;
};
std::vector<std::string> Arguments::arguments;
void f()
{
// use Arguments anywhere else:
std::cout << Arguments::Get(0);
}
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
Arguments::arguments.push_back(argv[i]);
}
f();
}
Note that special care is needed to avoid bugs at program shutdown, when static objects are destroyed. You must make sure that no destructor of a static object accesses Arguments, or else you risk undefined behaviour.
Is it possible to get the command line arguments without receiving them via int main(int, char**) ?
No (at least, not in portable manner), however you could put the usual argc, argv into some global variable (or other global data, often after parsing). And that could also be into some static data with other functions in the same translation unit retrieving it. Hence a reasonable (readable and portable) approach would be:
static int myargc;
static char **myargv;
int GetArgumentCount(void) {
return myargc;
}
char**GetArguments(void) {
return myargv;
}
int main(int argc, char**argv) {
myargc= argc;
myargv= argv;
/// etc....
Notice that on some systems or some implementations you might access to the command line arguments in some other ways.
dirty Linux specific tricks
For example, on Linux, using proc(5), you might parse /proc/self/cmdline but it is unreasonable to do that (on your Linux system, try to run od -cx /proc/self/cmdline in your terminal to guess what I mean), so I still recommend using int main(int argc, char**argv) and storing, in some global or static data, the argc and argv, or more probably, do some parsing of program arguments.
So on Linux, you might code your GetArgumentCount and GetArguments functions (by parsing /proc/self/cmdline, see also this) but it would be foolish to do so without using argc and argv from main (even if it is technically doable). Coding such a crazy GetArgumentCount and GetArguments which parses /proc/self/cmdline is left as an exercise to the masochistic reader.
Perhaps you need that because some static data's constructor -running before main and called before it from crt0- uses them; but in that case, your program's design is IMHO very wrong. I have no idea if similar dirty tricks are doable in Windows.
If you really think that is a good idea, you can easily make cor command line arguments global:
int argc_ = 0;
char** argv_ = NULL;
int main(int argc, char* argv[]) {
argc_ = argc;
argv_ = argv;
// ...
}
In standard C++, can the main function and its parameters have attributes?
For example, is this following legal?
[[noreturn]] int main() { std::abort(); }
or something like
[[nodiscard, carries_dependency]]
int main(int argc [[maybe_unused]],
char * argv [[carries_dependency, maybe_unused]] [])
{ /* ... function body omitted ... */ }
Yes, it is legal. There is no wording in the C++ standard (in [basic.start.main], [dcl.attr], or elsewhere) to prevent any of this. One can even mark main() as [[deprecated]] if wanted.
I'm doing some C# code which is using DLLImport to call a function inside my C++ DLL:
[DllImport("my.dll", EntryPoint = "#16", CallingConvention = CallingConvention.StdCall)]
private static extern void sendstring(string s);
I call it like this in C#:
sendstring("Test1\\0test2\\0");
My C++ DLL needs to create a static const char XY[] = "Test1\0test2\0"; from this, since I need that for calling another DLLs function from inside my c++ DLL like this:
functiontootherdll(sizeof(s),(void*)s);
So my code in C++:
extern "C" {
void MyClass::sendstring( const char *s) {
functiontootherdll(sizeof(s),(void*)s);
}
The problem: It is working, if I define the thing manually inside my C++ DLL like this:
static const char Teststring[] = "Test1\0test2\0";
functiontootherdll(sizeof(Teststring),(void*)Teststring);
but it is not taking the const char *s when calling this from my C# file (it will report different errors from the called other dll).
I would need to know how I can cast the const char *s to something like static const char s[] or such.
As you realize I have little clue about all this, so any help is very welcome!
Alright, I found out a way I think:
I modified my C++ to:
extern "C" {
void MyClass::sendstring( const char *s) {
int le = strlen(s);
char p[256];
strcpy(p,s);
char XY[sizeof(p) / sizeof(*p) + 1];
int o=0;
for (int i = 0; i<le;i++) {
if (p[i] == ';') {
XY[i] = '\0';
} else {
XY[i] = p[i];
}
o++;
}
XY[o] = '\0';
functiontootherdll(sizeof(XY),(void*)XY);
}
Afterwards the function call to
functiontootherdll(sizeof(XY),(void*)XY);
is working fine.
Pls note that I send from my C# code now a string like "Test1;test2;test3;...", trying with the \\0 as separator did not work out. My call with C# is:
sendstring("Test1;test2;test3");
I don't know if this is a smart solution, but at least it is one :)
I'm using opengl, using the GLUT and GLEW libraries to create a plugin for a certain application.
This plugin doesn't start with a simple int main(argc, argv). So i can't pass these values to glutInit().
I tried something like this:
glutInit(0, NULL); <--- Crash
GLenum err = glewInit();
But i crashed when it tried to call the glutInit() function. Can i reconstruct those params some how, so that it won't crash and still be able to use the Glut library..??
You can do it like this :
#include <GL/freeglut.h>
int main()
{
char fakeParam[] = "fake";
char *fakeargv[] = { fakeParam, NULL };
int fakeargc = 1;
glutInit( &fakeargc, fakeargv );
//...
}
but take a note that it is an ugly hack.
You might have to call glutInit with a valid argv parameter, even if you don't have any:
char *my_argv[] = { "myprogram", NULL };
int my_argc = 1;
glutInit(&my_argc, my_argv);
Edit
It might also be that the first parameter is a pointer to an int, and it can't be NULL? Then it might be enough to only pass a valid argc parameter:
int my_argc = 0;
glutInit(&my_argc, NULL);
Note the following code from the source (freeglut_init.c:677):
void FGAPIENTRY glutInit( int* pargc, char** argv )
{
char* displayName = NULL;
char* geometry = NULL;
int i, j, argc = *pargc;
...
(Note the dereferencing.)
It seems that glutInit() does require a minimum of the process name, although the man page doesn't shed any light on this.
I propose this as a de-facto standard for initializing glut applications.
static inline void glutInstall()
{
char *glut_argv[] = {
"",
(char *)0
};
int glut_argc = 0;
glutInit(&my_argc, my_argv);
}
This function can be modified on per-application basis to provide glut with the arguments it needs(if any), while permanently solving the issue of everyone asking why you are passing command line arguments to a 3rd party library.