Notes:
I am compiling on OSX using Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Specifically, I am trying to compile a monolithic source from LibIIR, a filter library maintained here by Laurence Withers.
I've already looked at this answer here about using both <complex> and <complex.h> in the same file.
Setup:
I have a file iir.h like so:
#include <complex.h>
#ifdef __cplusplus
extern "C" {
#endif
...
I have C++ source and header files libiir++.cpp and iir++.h like so:
/*** libiir++.cpp ***/
// we need to include "iir.h" first, as it pulls in <complex.h>, which we need
// to take effect before "iir++.h" pulls in <complex>
#include "iir.h"
// now remove the preprocessor definition of complex to _Complex, which is fine
// for the C header but not good for the C++ header
#undef complex
#include "iir++.h"
namespace IIR {
...
-
/*** iir++.h ***/
#include <complex>
namespace IIR {
...
Problem:
clang gives me the following error when compiling:
./iir.h:570:15: error: expected ';' after top level declarator
double complex iir_response_c(const struct iir_coeff_t* coeff, double freq);
^
;
Evidently, the new <complex> import is not happening--or #undef complex is happening again--but I don't see how. Any advice on what might be going wrong, or what to check?
<complex.h> is a C header and it is not compatible with C++.
C++ defines C library compatibility through headers named in the pattern <c***>. So, the C++ counterpart to <complex.h> is named <ccomplex>. Here's what the C++ standard has to say about that:
Header <ccomplex>
The header behaves as if it simply includes the header <complex>.
If you attempt to use the C complex number library, you just get the C++ one instead.
Bottom line: you simply cannot run C complex math through a C++ compiler. At best, you can use the preprocessor to generate equivalent programs depending on __cplusplus.
For example,
#if __cplusplus
# include <complex>
typedef std::complex< double > cdouble;
#else
# include <complex.h>
typedef double complex cdouble;
#endif
Note, std::complex< double > and double complex are layout-compatible per C++14 [complex.numbers] §26.4/4 and C11 §6.2.5/13. The intent seems to be that you can use cdouble for cross-language function prototypes, although strictly speaking it depends on the ABI.
Incidentally, the C++ standard does define what happens when you #include <complex.h>, but it doesn't make any sense:
Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).
So, #include <complex.h> should give you a global ::complex<T>. This is a defect in the standard.
Related
I have this project, where two other projects get included, that provide headers for the same DLL. In one header the declarations are put into a namespace, in the other one not.
That works well for GCC and MSVC, but I can't convince clang to compile it..
So a minimal example would be:
x.h:
#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__
namespace XX {
struct Type {
std::string name;
};
extern "C" int Func(Type);
}
incl.h:
#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__
struct Type {
std::string name;
};
extern "C" int Func(Type);
main.cpp
#include "incl.h"
#include "x.h"
int main()
{
return 0;
}
G++ complains with a warning, but that is turned off with # pragma GCC system_header.
So, how can I get clang to build in an environment like this?
[dcl.link] At most one function with a particular name can have C language linkage. Two declarations for a function
with C language linkage with the same function name (ignoring the namespace names that qualify it) that
appear in different namespace scopes refer to the same function. ...
As such, ::Func and XX::Func must refer to the same function. But your two declarations have different parameter lists - one takes a parameter of ::Type while the other takes a parameter of XX::Type. As such, they cannot be the same function, and thus the quoted rule is violated, and the program is ill-formed.ever
A few ways to fix the program:
Rename either XX::Func or ::Func so that they are separate functions. Make sure that there is a definition for each.
In incl.h, include x.h and replace the definition of ::Type with using XX::Type. So that each Type refers to the same type, and consequently both function names refer to the same function. Make sure that there is only one definition.
In x.h, include incl.h and replace the definition of XX::Type with using ::Type. To achieve the same as above.
The latter is by the way how some standard library implementations implement <cstdlib> and its friends. They include the corresponding C standard library header (<stdlib.h> in the case of <cstdlib>) which declares everything in global namespace (the only "namespace" in C), and then they pick all of the standard functions and types into std namespace with using ::whatever.
P.S. Don't use #pragma GCC system_header (unless you're writing a system header). It will suppress all warnings (except those produced by #warning directive).
The code below runs fine in C.
But in C++ (std-C++00), the compilation fails.
#include <complex.h>
int main()
{
float complex a = 0.0;
return 0;
}
Here's the errors i am facing
Error: complex is not pat of 'std'
Error: expected ';' before a
I have read the solution to the problem I am facing here, and I am also aware of std::complex.
But my problem is that, I must port an enormous amount of C code to C++,
where complex numbers are declared and used, as shown above.
So any way of to do it ?
what other options do I have ?
#include <complex>
int main()
{
// Both a and b will be initialized to 0 + 0i.
std::complex<float> a;
std::complex<float> b = 0.0f;
return 0;
}
The C99 complex number syntax is not supported in C++, which instead includes the type std::complex in the C++ standard library. You don't say what your motivation for porting the code is but there may be a couple different things you can do.
std::complex is specified in C++11 to be layout compatible with C99's complex. Implementations of earlier versions of C++ generally happen to provide std::complex layout compatibility as well. You may be able to use this to avoid having to port most of the code. Simply declare the C code's interface in C++ such that C++ code can be linked to the C implementation.
#include <complex.h>
#ifdef __cplusplus
extern "C" void foo(std::complex<float>);
#else
void foo(complex float);
#endif
You may need to modify the above for your implementation. You have to ensure that both name mangling and calling conventions are consistent between the two declarations.
Alternatively, there are compilers that support the C complex syntax in C++ as an extension. Of course since the C complex macro would interfere with std::complex that macro does not get defined in C++ and you instead have to use the raw C keyword _Complex. Or if you don't use std::complex anywhere and you're never going to then you could just define the macro yourself: #define complex _Complex.
#ifdef __cplusplus
#define complex _Complex
#else
#include <complex.h>
#endif
int main()
{
float complex a = 0.0;
return 0;
}
This #define prohibits any use of the C++ complex headers. (and technically it causes undefined behavior if you make any use at all of the standard library, but as long as you avoid the headers <complex>, <ccomplex>, and <complex.h> it will probably be okay in practice.
If you really do need to port the entire codebase to standard C++, you might consider porting it not directly to idiomatic C++, but instead to 'portable' C. I.e. code that compiles as both C and as C++. This way you can continue building as C while you incrementally port it and verify that it continues to work correctly throughout the porting process.
To do this you'll do things like replace float complex with a typedef and then define the typedef appropriately in each language, use the C header <tgmath.h>, define other macros in C to correspond with the C++ complex interface, etc.
#include <complex.h>
#include <math.h>
#ifdef __cplusplus
using my_complex_type = std::complex<float>;
#else
#include <tgmath.h>
typedef float complex my_complex_type;
#define real creal
#define imag cimag
#endif
#define PRI_complex_elem "f"
void print_sine(my_complex_type x) {
x = sin(x);
printf("%" PRI_complex_elem "+%" PRI_complex_elem "i\n", real(x), imag(x));
}
The answer from bames53 has been accepted and is very helpful. I am not able to add a comment to it, but I would suggest that perhaps
void print_sine(my_complex_type x) {
x = sin(x);
printf("%" PRI_complex_elem "+%" PRI_complex_elem "i\n", real(x), imag(x));
}
should use csin(x) in lieu of sin(x).
I need to include the header of a C library into my C++11 code. Now, the header provides routines and data structures that involve plenty of double complex all over the place. E.g.,
#include <complex.h>
//..
typedef struct parameters
{
// ...
double complex Vud;
} parameters;
// ...
double complex polylog(int n, int m, double x);
I bring this file into my C++11 source wrapped in extern "C" { #include "include.h" } (that's the actual filename, believe it or not). And g++ (tried 4.7.3 and 4.8.2) and clang (3.3) go nuts if I have -std=c++11 added.
The millions of lines of g++ errors include plenty of:
include/g++-v4/cmath:98:3: error: template with C linkage
And clang gives:
cmath:84:3: error: declaration conflicts with target of using declaration already in scope
abs(double __x)
^
/usr/include/stdlib.h:773:12: note: target of using declaration
extern int abs (int __x) __THROW __attribute__ ((__const__)) __wur;
^
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/cstdlib:245:14: note: using declaration
using std::abs;
^
I am not sure how to get around this. What is the correct way to do this? Clearly these must be inter-operable, but I do not know the trick.
In 100% standard C++, you just plain cannot include standard headers in an extern "C" block. You would need to modify your include.h header to be C++-friendly, by first including its required headers outside of extern "C", and declaring its own names inside an extern "C" block.
17.6.2.2 Headers [using.headers]
[...]
3 A translation unit shall include a header only outside of any external declaration or definition, and shall include the header lexically before the first reference in that translation unit to any of the entities declared in that header.
Doing
extern "C" {
#include <complex.h>
}
is invalid, because the header is then included inside of a declaration. This applies even if it's another header that only indirectly includes <complex.h>.
What may work on common implementations, as a workaround if modifying include.h is impractical, is to first manually include all the headers that include.h would include itself. Assuming those headers use the appropriate guards to make a second inclusion a no-op, the fact that include.h includes them will then not cause any errors.
I have a problem with declaring a function in one of my header files (C++), this is how the file looks:
#ifndef MACTRANSFERINCLUDE
#define MACTRANSFERINCLUDE
#ifdef USE_MAC
#include <string>
#include <boost/shared_ptr.hpp>
using namespace std;
boost::shared_ptr<wstring> browseFolder();
boost::shared_ptr<vector<wstring>> getFilesInDirRecursiveImplementation(boost::shared_ptr<vector<wstring>> dirs, boost::shared_ptr<vector<wstring>> files);
#endif
#endif
When building the project (for Mac OSX in XCode), I get "'dirs' was not declared in this scope".
If I also declare a function
boost::shared_ptr<vector<wstring>> foo();
I get the error "A function call cannot appear in a constant-expression". I'm not very familiar with C++, so any help would be appreciated.
You need to include header <vector>
#include <vector>
Maybe it is the reason of the error.
I do not see a big difference between declaration
boost::shared_ptr<wstring> browseFolder();
and
boost::shared_ptr<vector<wstring>> foo();
So the compiler should issue error
"A function call cannot appear in a constant-expression".
also for the first declaration.
The only difference is that the second declaration is used vector that was not declared. At least it is not seen where it is declared in your header.
Also it is a bad idea to use directive
using namespace std;
I would remove it and write
boost::shared_ptr<std::wstring> browseFolder();
boost::shared_ptr<std::vector<std::wstring>> getFilesInDirRecursiveImplementation(boost::shared_ptr<std::vector<std::wstring>> dirs, boost::shared_ptr<std::vector<std::wstring>> files);
The other reason is that maybe you need to insert a blank between symbols >> For example
boost::shared_ptr<std::vector<std::wstring> > dirs
It seems indeed that you have an old compiler that does not use the new syntax for the pair of symbols >> in template argument declarations. So you have to insert a blank between these two symbols > >
I would like to know if this is the correct way to port a C library to C++; for this example I wrote a 2 line C header with a function and a typedef managing a pointer.
lib.h
#ifndef LIB_H
#define LIB_H
#include <math.h>
double foo(double a) { return (log(a)); }
typedef double (*PtoFoo)(double);
#endif // LIB_H
lib.hpp
#ifndef LIB_HPP
#define LIB_HPP
namespace lib {
extern "C" {
#include "lib.h"
}
}
#endif // LIB_HPP
and a little test in C++11
#include <iostream>
#include "lib.hpp"
#include <functional>
int main() {
// call to the function
std::cout << lib::foo(42354.343) << "\n";
// trying the pointer to function type
lib::PtoFoo ptr = lib::foo;
std::function<double(double)> f(ptr);
std::cout << f(342.4) << "\n";
return (0);
}
right now my attention is focused on pointers, function pointers and functions, but in general I would like to know if this is the correct way to port standard C code to C++ and using the new c++ interface with namespaces without possible backfires .
Yes, that is the correct way to do it.
Alternatively, you can use the __cplusplus preprocessor token to define the C++ interface in the same header file:
#ifdef __cplusplus
namespace lib {
extern "C" {
#endif
typedef ...
#ifdef __cplusplus
}
}
#endif
The advantage of this approach is that only a single header file is required.
As I commented, C++ is designed to be compatible with C, so just wrapping your C library headers with the appropriate extern "C" { and } /* end extern "C"*/; is enough.
However, you may want to design a C++ friendly interface to your library. This requires some thoughts, and some code (most of it in C++ specific header files). For instance, you may want to provide interfaces using C++ object, overloading, operator, and template facilities.
I can't help more, but look for examples at: libonion and its C++ bindings, GTKmm which is a large C++ binding to GTK (and companion libraries like Glib...), the C++ class interface to gmplib, or even the newest C++11 standard thread library (i.e. std::thread etc, etc...) which could be viewed as a clever C++ wrapping of pthreads ....
I believe that each library could have its own C++ wrapping... How to design that is up to you... (depends a lot on the wrapped library, your available time, and your fluency with C++...).