How to build object using C++ vector library in gcc? - c++

so I have some working code that calls gcc in a makefile. I then add my own class that uses the c++ vector stl, and I want to compile the same object.
If I just run the same command, I get an error:
fatal error: vector: No such file or directory
#include <vector>
If i try to use g++ instead to compile, I instead get a million errors, so I'm guessing that I shouldn't do that.
I googled how to add a c++ library to a gcc call, and I was told to use
gcc -lstdc++
However, that doesn't seem to have any effect. How can i go about building this object?
Would using g++ be the standard way? If I use g++ instead of gcc it seems like there are many conversion errors of this type:
globals.c:1381:50: error: invalid conversion from 'void*' to 'Global*' [-fpermissive]
struct Global *g = calloc(1,sizeof(struct Global)); /* allocate viewer context */
as well as an error of previous declaration:
d:\mingw\include\getopt.h:46:12: error: previous declaration 'int getopt(int, char* const*, const char*)' here
extern int getopt( int, char * const [], const char * );

There are quite a few issues here. First, the "gcc" executable will compile both C and C++ code, but it typically determines whether it should compile as C or C++ based on the file suffix. In your case, it appears to have tried to compile "globals.c" as a C source file instead of a C++ source file. The C compiler does not include the proper directory in the list of internal include paths so it will not even try to open the <vector> include. To compile as C++, you can force it with g++ or by changing the name of your source file to have a .cpp or .C suffix.
If you have more than one source file, then you are going to have more work to do. You will probably either need to compile everything with the C++ compiler, or will need to learn about "extern 'C'" and fix the interfaces between C++ and C. This may be more trouble than it is worth.
Next, you will need to address all of the errors in your compilation. It looks like the main problem you show has to do with typecasts. Those were more permissive under C than C++.
I would suggest that you take out the vector code, and keep using a pure C solution in your case. You have to perform the memory management yourself, but it isn't too hard. I have used realloc() in the past to resize memory. You'll need to keep track of a pointer to the allocated memory, the number of allocated objects and potentially the total size of the buffer.

The first error is because there is no automatic conversion from void * to other pointer types in c++. Which is not the case in c, so the code would compile correctly with a c compilier, to solve that you just need to cast the return value like this
Global *g = reinterpret_cast<Global *>(calloc(1,sizeof(Global)));
also notice that you don't need struct for declarations in c++.
I'd recommend the new operator, because if you add a constructor to struct Global it will automatically invoke the cosntructor, also
Global *g = new Global;
notice however that unlike calloc() the struct members here are not initialized to 0.
The important thing to know is that c and c++ are different languages, you can easily write code that would compile with a c compiler but not with a c++ compiler, like the code above, the other way it's even easier.

Related

How to build program without cast result of calloc in Xcode?

I'm trying to use calloc in my program. With an explicit cast it compiles and runs fine, but when I try to remove the explicit cast of malloc I see the following error:
Assigning to '... *' (aka '....... *') from incompatible type 'void *'
How can I compile my code without an explicit cast of calloc in Xcode?
You are attempting to compile your C code as C++.
While it is true that some C code is also valid in C++, you have come across an example of C code that isn't valid in C++.
That is, C++ does not offer the implicit conversions to/from void * that C does.
You should always compile your C code using a C compiler, for the following three reasons:
You don't need to compile C code using a C++ compiler.
You're missing out on the best parts of C++.
You're missing out on the best parts of C.
The only reason people try to compile C code with a C++ compiler is that they anticipate using their C code in a C++ project. However, this is unnecessary because you can usually compile your C code using a C compiler, compile your C++ code using a C++ compiler and then link the two together. For example:
gcc -c c_code.c
g++ -c cpp_code.cpp
gcc cpp_library.o c_library.o
In C++, it is generally a bad idea to use *alloc functions. Those who program specifically in C++ will usually cringe at *alloc use.
In C, it is always a bad idea to explicitly cast void *, as the link you provided explains. Those who program specifically in C will cringe at unnecessary boilerplate that potentially introduces bugs.

Compiling C/C++ code on MacOS

I have a C/C++ project that I started on Linux and I want to port it now to MacOS. The issue I am facing is the following:
My source code links to a C library (the abc tool from https://bitbucket.org/alanmi/abc) and uses header files from that library. When compiling on Linux everything goes well but things tend to break when compiling on MacOS. The error I am getting is the following:
abc/src/misc/vec/vecPtr.h:895:33: error: too many arguments to function call, expected 0, have 2
It is mainly due to the way function pointers are handled on the two systems. As I have understood from searching online is that in C, function pointers with empty parenthesis () are considered to have a variable number of arguments while this is not the case in C++. It seems that g++ on Linux is able to compile such code correctly while on MacOS it is failing.
Can anyone please help with some insights on this issue?
Thanks
The library is declaring function pointer arguments like this:
int (*Vec_PtrSortCompare)()
and then invoking them like this:
Vec_PtrSortCompare(p->pArray+i, p->pArray+k-1)
In C, a function declarator with an empty argument list doesn't specify how many arguments it takes. Therefore, you can legally pass as many arguments as you want to such a function. However, such "variadic" functions are considered deprecated.
In C++, however, a function declarator with an empty argument list specifies that the function takes zero arguments.
This difference means that you cannot compile a header file like this with a C++ compiler. You have two options: you could compile the parts of your program using this header with only a C compiler and make a library or set of object files, then compile the rest of your program with a C++ compiler (assuming you have C++ parts).
Alternatively, you could fix the function declarations. From context, it appears that the functions should be declared as
int (*Vec_PtrSortCompare)(const void **a, const void **b)
(In proper C++, this would be a templated function to avoid having to use void *; however, C does not have templates.)

VS 2013 error C2664 when trying to compile a .c file as .cpp

I am on my way of programming my first external for Max 6, but the entitled error is holding me back. I have crawled for a week the web to find a solution to the entitled problem, but no luck. There are many topics related to
error C2664: cannot convert parameter 1 from 'X' to 'Y'
but none of the proposed solutions was suitable for my case, since it seems to be a Max object case-specific.
More to the point, I have a main .c file for my external that makes use of various other .cpp files and libraries. For that reason I want to compile it as a .cpp file. As far as I know, there shouldn't be a problem with that. However, when I am trying to compile it in Visual Studio I get the following error:
error C2664: 't_object *object_alloc(t_object *,const char *,...)' : cannot convert argument 1 from 'void *' to 't_object *' "
Has anyone faced and managed to solve any similar issue? Is it the case that I am missing something more profound?
Thank you in advance!
C++, unlike C, does not permit implicit conversion of a void pointer to a non-void pointer. It seems that you are trying to pass a void pointer as the first argument to that function, but since it can't be converted to the parameter type, an error occurs.
You can solve this by casting the void pointer directly to the target pointer type.
object_alloc(static_cast<t_object*>(p), ...)
(FYI, the conversion in the reverse direction---non-void pointer to void pointer---is a standard conversion and can occur implicitly. static_cast is allowed to perform the reverse of standard conversion sequences.)
In C there is an implicit conversion from void* to any data pointer type.
Together with C's implicit function declarations this means that in C it's not a good idea to cast the result of e.g. malloc, because with a missing header (no malloc declaration) that will implicitly declare malloc with result type int, and at least the local code will compile with no visible error... :(
In C++ there is no implicit conversion from void*.
So in C++ one not only should but most often must cast the result of e.g. malloc.
Happily C++ does not have implicit function declarations. :)
A good solution for your specific problem may be to compile the C file as C (duh).
However, be aware that the top level control of a combined C and C++ program, should better be C++. I.e. compile main as C++. That's because C++ has some extra runtime library requirements such as dynamic initialization of things.
Instead of an implementation file that can compile as either C or C++, consider just a header (with only pure declarations) that can be used with both languages. This is the common way to do things. You can use a conditional extern "C" to make the declarations work fine also in C++.

C++ error: invalid conversion from 'void*' to 'char*'

I have this C++ code:
#include <stdlib.h>
int main(){
char *Teclas;
Teclas = calloc(1024,sizeof(char));
}
And the compiler is giving the following error:
error: invalid conversion from `void*' to `char*'
What does this error mean and how do I fix it?
The problem is that you're trying to compile C with a C++ compiler. As the error message says, this line:
Teclas = calloc(1024,sizeof(char));
tries to convert the untyped void* pointer returned by calloc into a typed char* pointer to assign to the variable of that type. Such a conversion is valid in C, but not C++.
The solution is to use a C compiler. It looks like you're using GCC, so just rename the source file to something.c, and build with gcc rather than g++.
If you really must use a compiler for the wrong language, and don't feel like rewriting this in idiomatic C++, then you'll need a cast to force it through the compiler:
Teclas = static_cast<char*>(calloc(1024,sizeof(char)));
or, if you want the code to remain valid C:
Teclas = (char*)calloc(1024,sizeof(char));
But don't do that: use the right compiler for the language. Unless this is the first stage in converting the program to C++; in which case, the next thing to do is get rid of these allocations and use std::string instead.
calloc() returns a void*. You need to cast its value to whatever type Teclas is, which appears to be a char*. So Teclas = (char*)calloc(...).
void int main(int argc,char *argv[])
uhm... perhaps just int main(int argc, char *argv[])...
Apart from that: this looks like C code. Nothing in these lines suggests that you use C++. The error you are seeing is the result of you treating C code as if it was C++, whereas it isn't, because C is not C++, C++ is not C, and neither is the subset of the other one.
Compile your C code with a C compiler.
The best solution is to just compile your code with a C compiler, as this is C code. You really shouldn't compile C code as if it were C++. However, to directly answer your question, you can force the C++ compiler to compile your C code (which is very bad!!!!).
In C++, whenever you use any function of the alloc family, you must cast the return value to the type of your lvalue. So, in this case:
Teclas = (char*)calloc(1024, sizeof(char));
The way in which I would do the above is like this:
Teclas = (char*)malloc(1024 * sizeof(*Teclas));
The benefits here: If you change the type of Teclas, you will still end up with the correct allocation size. Also, I just prefer using malloc in general.
Additionally, you have major issues throughout your code. For one thing, void int main(...)???? And you never initialize the contents of Teclas before you print it, but you free it and calloc it again for some reason. I think you meant to make that a do while loop, but there is no do.
Also, void KeyLogger(); is WRONG. That is how you declare the function, but since it is a declaration, it should be outside of main.
On the android NDK JNI, even with typecasting, old style or new style, the error still doesn't go away.
buffer = (char *) malloc(10);
xxxx=static_cast<char*>(calloc(1024,sizeof(char)));
To make the errors go away, an extra include needs to be added to the path and symbols.
Project -> properties -> C/C++ general -> Path and symbols
On the Includes tab/GNU C++, add the following path (with the appropriate gcc version 4.6, 4.8...) Of course on windows, the path would be be a windows path....
{NDKROOT}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.6/include
If you can make sure there is no other error in your code, you can add g++ flag: -fpermissive to put the error into warning.
exp: g++ -fpermissive yourcode.cpp

How does this function definition work?

I generated a hash function with gperf couple of days ago. What I saw for the hash function was alien to me. It was something like this (I don't remember the exact syntax) :
unsigned int
hash(str, size)
register char* str;
register unsigned int size;
{
//Definition
}
Now, when I tried to compile with a C++ compiler (g++) it threw errors at me for not having str and size declared. But this compiled on the C compiler (gcc). So, questions:
I thought C++ was a superset of C. If its so, this should compile with a C++ compiler as well right?
How does the C compiler understand the definition? str and size are undeclared when they first appear.
What is the purpose of declaring str and size after function signature but before function body rather than following the normal approach of doing it in either of the two places?
How do I get this function to compile on g++ so I can use it in my C++ code? Or should I try generating C++ code from gperf? Is that possible?
1. C++ is not a superset, although this is not standard C either.
2/3. This is a K&R function declaration. See What are the major differences between ANSI C and K&R C?
.
4. gperf does in fact have an option, -L, to specify the language. You can just use -L C++ to use C++.
The Old C syntax for the declaration of a function's formal arguments is still supported by some compilers.
For example
int func (x)
int x
{
}
is old style (K&R style) syntax for defining a function.
I thought C++ was a superset of C. If its so, this should compile with a C++ compiler as well right?
Nopes! C++ is not a superset of C. This style(syntax) of function declaration/definition was once a part of C but has never been a part of C++. So it shouldn't compile with a C++ compiler.
This appears to be "old-school" C code. Declaring the types of the parameters outside of the parentheses but before the open curl-brace of the code block is a relic of the early days of C programming (I'm not sure why but I guess it has something to do with variable management on the stack and/or compiler design).
To answer your questions:
Calling C++ a "superset" of C is somewhat a misnomer. While they share basic syntax features, and you can even make all sorts of C library calls from C++, they have striking differences with respect to type safety, warnings vs. errors (C is more permissible), and compiler/preprocessor options.
Most contemporary C compilers understand legacy code (such as this appears to be). The C compiler holds the function parameter names sort of like "placeholders" until their type can be declared immediately following the function header name.
No real "purpose" other than again, this appears to be ancient code, and the style back in the day was like this. The "normal" approach is IMO the better, more intuitive way.
My suggestion:
unsigned int hash(register char *str, register unsigned int size)
{
// Definition
}
A word of advice: Consider abandoning the register keyword - this was used in old C programs as a way of specifying that the variable would be stored in a memory register (for speed/efficiency), but nowadays compilers are better at optimizing away this need. I believe that modern compilers ignore it. Also, you cannot use the & (address of) operator in C/C++ on a register variable.