Compiling C/C++ code on MacOS - c++

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.)

Related

Figure out function signatures of precompiled functions during JIT in LLVM

I am currently working on implementing a JIT compiler using LLVM.
The problem I have is that a portion of the compiler runtime is implemented in C.
From my intermediate representation, I can generate all native functions. However, certain operations in the language require calls to these external C-functions.
The problem I have is that I do not from my IR know the exact types of parameters passed to these functions, they might take an int, or they might take a float. The previous code generation was based on C, and the weak typing of C allowed to call these functions with no hassle. However, when generating LLVM-IR I need to know the signatures of these pre-compiled functions, is there any way to figure out the signature using the orc-API or some other method, or would it be better to just hard code the configuration for each necessary function?
The solution I implemented for this problem follows the following simple scheme.
During compilation calls to these functions are generated the signature simply being based on what parameters and return values are passed to the pre-compiled function in question.
This works well for my example since I use the C calling convention with LLVM. The C calling convention to quote the LLVM homepage tolerates mismatch:
"This calling convention (the default if no other calling convention is specified) matches the target C calling conventions. This calling convention supports varargs function calls and tolerates some mismatch in the declared prototype and implemented declaration of the function (as does normal C)." [1]: https://llvm.org/docs/LangRef.html#calling-conventions

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

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.

Is there any way to replace a function in a library?

I work with a library which defines its internal division operator for a scripting language. Unfortunately it does not zero-check the divisor. Which leads to lot of headaches. I know the signature of the operator.
double ScriptClass::Divide(double&, double&);
Sadly it isn't even a C function. Is there any way I could make my application use my own Divide function instead of ScriptClass::Divide function?
EDIT:
I was aware of dlopen(NULL,..) and replacing "C" functions with user defined ones. Can this be done for class member functions (Without resorting to using mangled names)?
Various linkers and dynamic linker implementations will provide something that looks like a solution to this, as others have mentioned.
However, if you redefine one C++ function using any of those features (GNU ld's --wrap, ld.so's LD_PRELOAD, etc.), you are violating the one-definition rule and are thus invoking undefined behaviour.
While compiling your library, the compiler is allowed to inline the function in question in any way that it sees fit, which means that your redefinition of the function might not be invoked in all cases.
Consider the following code:
class A
{
public:
void foo();
void bar();
};
void A::foo()
{
std::cout << "Old version.\n";
}
void A::bar()
{
foo();
}
GCC 4.5, when invoked with -O3, will actually decide to inline the definition of foo() into bar(). If you somehow made your linker replace this definition of A::foo() with a definition of your own, A::bar() would still output the string "Old version.\n".
So, in a word: don't.
Generally speaking it's up to the programmer, not the underlying divide operator to prevent division by zero. If you're dividing by zero a lot that seems to indicate a possible flaw in the algorithm being used. Consider reworking the algorithm, or if that's not an option, guard calls to divide with a zero check. You could even do that inside a protected_divide type function.
All that being said, assuming that since it looks like a C++ function you have a C++ library compiled with all the same options you're using to build your application so name mangling matches you might be able to redefine the function into a .so and use LD_PRELOAD to force it to load. If you link statically, I think you can create the function into your own .o file and linking that prior to the library itself will cause the linker to pick up your version.
LD_PRELOAD is your friend. As an example, see:
https://web.archive.org/web/20090130063728/http://ibm.com/developerworks/linux/library/l-glibc.html
There's no getting away from the mangled names, I don't think, but you can use ld's --wrap option to cause a particular function to be given a new name based on its old name. You can then write a new version of it, and forward to the old version too if you like.
Quick overview here:
http://linux.die.net/man/1/ld
I've used this in the past to hook into malloc (etc.) without having to recompile the runtime library, though this wasn't on Linux (it was an embedded thing with no runtime loading). I didn't use it to wrap C++ functions, but if you can handle the C++ calling convention somehow, and you can create a function with the original function's mangled name, and get the compiler to accept a call to a function that has some ugly name with funny chars in it... I don't see why it shouldn't be possible to make it work.
Just short Q,
Cant you just wrap the class with your own code?
It'll be some headache at the start but after than you can simplify a lot of functions.
(Or even just wrap the function with a macro)

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.

Should External Routine Be Declared Always in Fortran?

In my Fortran code I made the following call to the dnrm2 routine:
d = dnrm2(n, ax, 1)
Just a simple call that would return me a double precision result.
The question is, should I declare the function at the start of my script? I found that if I don't declare it, when I compile the code in 32 bit Windows, then the result is correct.
But if I compile the code in 64 bit Windows, then the result isn't be correct.
Why is this so? Must an external routine always be declared in Fortran?
If you don't correctly describe your subprograms (subroutines and functions) to a calling program, the compiler may not correctly call them. Fortran compiles each unit separately, so the compiler doesn't "know", by default, about the characteristics of other subprograms. There are several ways that you can describe/declare a subprogram in Fortran 90/95/2003.
The easiest and best method is to place your subprograms into a module and then "use" that module in the calling program. This automatically makes the interface known to the compiler and will enable the compiler to check the consistency of actual arguments (in the call) and dummy arguments in the subprogram. It will also make known the return type of a function. The various subprograms in a module have their interfaces known to each other.
You can also write an "interface" containing a subprogram declaration that matches the declarations of the actual subprogram. (This method can be very similar to the style of including header files in C.) This method is more work and prone to error because you have to manually maintain consistency between the actual subprogram and interface whenever changes are made. The interface method is useful when you don't have the code to the subprogram or the subprogram is written in a language other than Fortran.
Or you can simply declare a function name to specify the type-return of the function, but this won't give you any checking of the arguments. In my opinion this method is weaker since having the compiler check argument consistency eliminates a major class of programming mistakes.
I don't do Fortran, but in C, the size of a pointer and the size of a long int varies between 32 and 64 bit OS'es, but the size of an int does not. Perhaps the program is using ints to do pointer arithmetic?