I would like to use a C Library and a C++11 library in my application. It seems the usage of "complex" in the C and C++11 library conflicts, and it produces compilation error.
A MWE is given here.
Contents of myLib_C.h:
#ifndef MYLIBC_H
#define MYLIBC_H
#include <math.h>
#include <complex.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef float complex cfloat;
typedef double complex cdouble;
#define myFunc_cfloat(r,i) ((float)(r) + ((float)(i))*I)
#define myFunc_cdouble(r,i) ((double)(r) + ((double)(i))*I)
#ifdef __cplusplus
} // extern "C"
#endif
#endif
The contents of myLib_CPP.h:
#ifndef MYLIBCPP_H
#define MYLIBCPP_H
#include "myLib_C.h" //uses myLib_C somewhere in this file
#include <iostream>
#include <complex>
inline void CppFunction()
{
std::cout<<"This file need to be compiled using C++11\n";
std::complex<float> a(10,100);
std::complex<float> b(1, 1);
auto c = a+b;
std::cout<<"c= "<<c<<std::endl;
}
#endif // MYLIBCPP_H
My main.cpp:
#include "myLib_C.h"
#include "myLib_CPP.h"
#include <iostream>
#include <complex>
int main()
{
std::cout<<"Hello World\n";
CppFunction();
return 0;
}
The contents of CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(myTest)
set(CMAKE_CXX_FLAGS "-std=c++11")
add_executable(myTest main.cpp)
When I compile, I get the following error:
error: expected initializer before ‘cfloat’
typedef float complex cfloat;
A similar problem was discussed in C Complex Numbers in C++?. The solution mentioned there is to replace complex with _Complex. This is not possible in my case as I will not be able to edit the C and C++ libraries.
extern "C" { ... } doesn't magically turn C code inside braces into valid C++ code, so this is out.
Both language standards require their respective complex numbers to have the same layout as an array of two numbers of the corresponding floating-point type (i.e. both C++ std::complex<float> and C float complex behave just like float[2], layout-wise). You can exploit this. For example:
#ifdef __cplusplus
using cfloat = std::complex<float>;
#else
typedef float complex cfloat;
#endif
Now you can declare a cfloat variable in one language and pass it to the other language, and this should work.
Related
I failed to define overloading functions with error message of error: conflicting declaration of C function if enclosing by #ifdef __cplusplus blocks.
Below is a simple code for an easy view. This piece of code worked fine without #ifdef __cplusplus blocks.
However, my project code does need #ifdef __cplusplus as it involves combination of C and C++ codes.
Command lines after #ifdef __cplusplus block should be C++, why did it fail to define the overloading function? How to fix this problem with presence of #ifdef __cplusplus blocks?
#include <iostream>
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
int add(int x)
{
return x;
}
int add(int x, int y)
{
return x + y;
}
int main() {
// cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
int X = add(2);
int Z = add(8,2);
cout <<X<<" "<<Z<<endl;
return 0;
}
#ifdef __cplusplus
}
#endif
Command lines after #ifdef __cplusplus block should be C++
First of all, I believe you have a misconception of #ifdef __cplusplus, this macro only checks if your compiler is a C++ compiler or not.
You rather need focus on extern "C" {}. This block of code explicitly tells your compiler, that codes inside this block must be in C language(not C++).
This is important since C and C++ have different mechanisms of storing and calling functions from binary. (Called name mangling). Better to say, C and C++ binaries are not compatible. So extern "C" will tell your compiler that your functions C codes, and those function names are not mangled.
So #ifdef __cplusplus checks if your code is C or C++; if your code is in C++, insert extern "C" { that tells your compiler that those codes in this block are C code.
And since function overloading is not a part of C language, your compiler will cause an error inside that block. (This matters with name mangling).
But this macro is mostly used in header files, not source files. Because the purpose of this macro is to enable your code to be included in both C and C++ code, but source files cannot be and must not be included by another source.
So I was posed the challenge of mimicking lambda definitions in plain C on the msvc compiler (it doesn't support gcc extensions) - I came up with a file inclusion solution which basically mirrors the file at the top. It works fine for most cases but what if I want to include a lambda inside my lambda:
#ifndef FIRSTPASS
#include <stdio.h>
//here comes your "nested" definitions
#define FIRSTPASS
#include "source.c"
#undef FIRSTPASS
main(){
#else
int global = 2;
int func()
{
//define another "lambda" here
printf("%d\n", global);
}
#endif
#ifndef FIRSTPASS
func();}
#endif
I am trying to use the LIBSVM package on Eclipse IDE using C.
In the README file, it states that "You need to #include "svm.h" in your C/C++ source files and
link your program with `svm.cpp'."
I already included "svm.h" in all my source files and I added my 'svm.cpp' file under the source code folder. However, I got an error "template with C linkage" in the 'svm.cpp' file.
Does the error have anything to do with the way I added the 'svm.cpp' file in my program? I really do not understand and I tried searching everywhere.
svm.cpp:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <float.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include <locale.h>
#include "libsvm.h"
#include "main.h"
#ifdef __cplusplus
extern "C" {
#endif
int libsvm_version = LIBSVM_VERSION;
typedef float Qfloat;
typedef signed char schar;
#ifndef min
template <class T> static inline T min(T x,T y) { return (x<y)?x:y; }
#endif
#ifndef max
template <class T> static inline T max(T x,T y) { return (x>y)?x:y; }
#endif
template <class T> static inline void swap(T& x, T& y) { T t=x; x=y; y=t; }
template <class S, class T> static inline void clone(T*& dst, S* src, int n)
.
.
.
.
.
.
.
.
#ifdef __cplusplus
}
#endif
What version of libsvm you are using, and where did you download it from?
This version of svm.cpp does not have extern "C" around templates.
If you added them yourself, you have no-one else to blame.
If your version came with extern "C", that version is broken: templates really can't have extern "C" linkage.
Update:
I added the extern "C" by myself because I thought it was necessary. Is it wrong?
Yes, it is.
when I did not add extern "C", there were more errors
You should accept this answer to your question, remove your modifications, and ask a new question detailing the other errors.
fellow programmers,
I'm new to the C preprocessor and have been recently trying to create a generic-like library in C (as an exercise), and I've come upon a little problem when creating header guards.
All the preprocessor macros are set up so I can include and use my headers like this:
#define TYPE int
#include "myheader.h"
#undef TYPE
#define TYPE float
#include "myheader.h"
#undef TYPE
int main(void){
//Do stuff
MyFunc_int();
//More stuff
MyFunc_float();
return 0;
}
But the problem appears when I need to include the headers in more than one file. Header guards are usually applied in this case, but since the header can be included once -for each type-, neither the usual construction nor #pragma once can be used.
My question then is: Is it possible to create a "variable" header guard to work for different TYPE definitions?
When you want to include the header from various compilation units, you could divide the header into a publich part that plays the role of the header and a private part that plays the role of a *.c file, for example:
#define M_CONCAT(a, b) a##b
TYPE M_CONCAT(TYPE, _min)(TYPE a, TYPE b);
#ifdef IMPLEMENT
TYPE M_CONCAT(TYPE, _min)(TYPE a, TYPE b)
{
return (a < b) ? a : b;
}
#endif /* IMPLEMENT */
Then you can include this header from multiple files, but you have to make sure that only one file defines IMPLEMENT before including the header:
#define IMPLEMENT // only in one file
#define TYPE float
#include "myheader.h"
#undef TYPE
#define TYPE int
#include "myheader.h"
#undef TYPE
This file could be a separate compilation unit, myheader.c. You must take care to implement the function for all types, however. (But the linker will tell you, which types you've missed.)
I suggest:
Remove the #include guards in myheader.h.
Create different header files for each TYPE.
intheader.h:
#pragma once
#define TYPE int
#include "myheader.h"
#undef TYPE
floatheader.h:
#pragma once
#define TYPE float
#include "myheader.h"
#undef TYPE
And then use:
#include "intheader.h"
#include "floatheader.h"
int main(void){
//Do stuff
MyFunc_int();
//More stuff
MyFunc_float();
return 0;
}
I think you're looking for something like this:
#if !defined HEADERGUARD && defined (TYPE==int)
#define HEADERGUARD
<stuff>
#endif
You may want to have HEADERGUARD_int and HEADERGUARD_float, depending on what you're doing inside the *.h file. More conventionally, people will break it into two *.h files.
So I have a header file let's say "header.h" which is protected as follows:
#ifndef __HEADER1_H
#define __HEADER1_H
//type and function def
typedef struct
{
float r; //process noise
float k; //process gain
}state_t;
int get_state(state_t* state, float b);
#endif
Now I have two other headers which I defined as follows:
#ifdef __HEADER2_H
#include "header.h"
//function def
#endif
Second header:
#ifdef __HEADER3_H
//function
//the reason it is done this way is for cnditional compiling such that if the caller
//defines __HEADER3_H t this file won't be included.
#include "header.h"
#endif
Now as I suspected the compiler complained that types and functions defined in header.h were not detected in the source implementation of header2 and header3. So I included header.h in the source files as well. Now the linker is complaining functions that are defined in header.h are multiply defined.
My understanding was since the header.h is protected by ifndef it will only be included once so I don't see the problem.
here is the error that I am getting:
Symbol get_state multiply defined(by kalman.o and dsp.o)
Is there any chance that I am doing something unusally wrong?
#ifndef __HEADER1_H
#define __HEADER_H
The problem is your guard (__HEADER_H) is different from what you are checking for (__HEADER1_H). Make these both the same value.
The typical "guard" for a header file is:
myheader.h:
#ifndef _MYHEADER
#define _MYHEADER
<do stuff>
#endif
Optionally where myheader.h is included, you can do:
#ifndef _MYHEADER
#include "myheader.h"
#endif
This is optional and basically is only to improve compile performance.