Error in creating library from C file - c++

I'm trying to call a C function defined in sample_c.c (with function declaration in sample_c.h) from a C++ code. I'm using this declaration in sample_c.h
extern "C" void print_c(void);
and this definition in sample_c.c
extern void print_c(void) {....}
and trying to generate lib which I want to link with my cpp code. I'm getting an error when trying to generate lib out of this C code.
gcc -c sample_c.c
error: expected identifier or ‘(’ before string constant
I'm unable to rectify this. Can someone suggest where am I going wrong.

extern "C" is not valid in C. To write a header that can be used for both C and C++ you have to make sure that the extern "C" is not visible when compiled as C:
#ifdef __cplusplus
extern "C"
#endif
void print_c(void);

Related

Alias a function in a different source file

I've got a .h file and three .cpp files. All cpp files include the .h file.
I want to create a useless function in one of the cpp files and use alias in the other cpp files to refere to this useless function. But if i move the function from important.cpp to useless.cpp it does not want to compile anymore. For some reason it doesnt see the function, even if its declared in the header.
useless.h
#ifdef __cplusplus
extern "C" {
#endif
extern void useless(void);
#ifdef __cplusplus
}
#endif
useless.cpp
#ifdef __cplusplus
extern "C" {
#endif
void useless(void) { }
#ifdef __cplusplus
}
#endif
important.cpp
void important(void) __attribute__((alias("useless")));
error: 'void important()' aliased to undefined symbol 'useless'
void important(void) attribute((alias("useless")));
Why are you using a bunch of extern "C" stuff?
If it's a C++ project and a global C++ function, you really should claim it's a C function. Doing so can lead to undefined reference-type errors, as the symbol names are different for C and C++.
What you're trying to do is probably impossible. Take a look at gcc docs https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html It says:
It is an error if ‘__f’ is not defined in the same translation unit.
So if you remove useless from the translation unit where important is it looks like an error to me.

C2732 - Linkage specification error

I'm using VS2008. I'm getting the following error.
BUILD: [02:0000000295:ERRORE] c:\wince700\platform\am33x_bsp\src\bootloader\bootpart\bootpart_e.cpp(61) : error C2732: linkage specification contradicts earlier specification for 'SdhcInitialize' {log="C:\WINCE700\platform\AM33X_BSP\SRC\BOOTLOADER\bldsys.log(103)"}
BUILD: [02:0000000297:ERRORE] NMAKE : fatal error U1077: 'C:\WINCE700\sdk\bin\i386\ARM\cl.EXE' : return code '0x2' {log="C:\WINCE700\platform\AM33X_BSP\SRC\BOOTLOADER\bldsys.log(104)"}
BUILD: [02:0000000299:ERRORE] clean TargetCompilePass -nologo BUILDMSG=Stop. BUILDROOT=C:\WINCE700\platform\AM33X_BSP CLEANBUILD=1 NOLINK=1 NOPASS0=1 failed - rc = 2. {log="C:\WINCE700\platform\AM33X_BSP\SRC\BOOTLOADER\bldsys.log(105)"}
file_1.cpp
extern "C"
{
// some extern declarations
extern void SdhcInitialize(DWORD slot);
}
file_2.c
void SdhcInitialize(DWORD slot)
{
//some code
}
Please guide me how to resolve.
I'm guessing that you have a header that contains a prototype for the SdhcInitialize() function, and that the header was written for use by C programs. So for example, the header file might include something like the following line:
SD_API_STATUS SdhcInitialize(DWORD slot);
without being enclosed in an extern "C" {} block (since the header is intended for C programs).
Additionally, I suspect that this header is being included - directly or indirectly - by file_1.cpp
This means that the header cannot be included in a C++ program without some additional work being done, otherwise the C++ program will see the declaration as meaning that SdhcInitialize() has C++ linkage.
You have two reasonable approaches to fixing this:
if you can modify the header, add the following lines around the declarations in the header:
#if __cplusplus
extern "C" {
#endif
// declarations go here
#if __cplusplus
}
#endif
This way, C++ files will have the declarations enclosed in a extern "C" linkage block, while C program will not see the extern "C" bits (which would otherwise confuse the C compiler).
I think an argument can be made that all C headers should include something like those lines so that the C functions can be consumed by C++ programs without hassle.
if you cannot modify the header for some reason, you can work around the problem by including the header in C++ files like so:
extern "C" {
#include "Sdhc-header.h"
}
If you surround a set of function declaration by extern "C" { ... }, you don't need to use an additionnal externkeyword in front of the function identifier.
extern "C"
{
// some extern declarations
SD_API_STATUS SdhcInitialize(DWORD slot);
}
When you try to include the "some header files of C" file in "C++ file"(the header file has some where extern "C" for some functions).
include the header earlier will solve the problem.
e.g. Try to move #include "myHeader.h" on the top lines of your C++ file.
This solves my problems.
Hope it helps....
I have solved this as follows (the other solutions did not work for me):
In the file vector.cc:
#define __INVECTOR //solves
#include "vector.h"
In vector.h:
#ifndef __INVECTOR
void function(...etc..);
#endif
This way the declaration isn't read unless we want to call the function from a different file.

c and c++ mixed

I need to call cpp method from c file.
I have written this interface for that..
cpp file
extern "C" void C_Test(int p){
Class::CPP_Test(p);
}
c file
extern void C_Test(int p);
void C_Function(){
C_Test(10); //error
}
I get error in c file "undefined reference to C_Test(int)"
any idea whats wrong?
You must declare extern only for function prototype, and ensure to link correctly. In addiction to this, CPP_Test(p) must be a static member of Class, otherwise your code does not work. At last, extern "C" must enclose in brackets its content, more like
extern "C"
{
void C_Test(int p)
{
Class::CPP_Test(p);
}
}
Tell us if this works.
Are you compiling both with a C++ compiler? C++ compilers may compile a C-source file as C++, in which case it will perform name mangling, so you need to be sure to compile the C source file with a C compiler.
I am using C++ compiler for both types of files.
Without "C" it works!! Also without extern "c" it works!

__cplusplus macro to tell g++ about C header declarations not working strangely

I have a mix of C C++ code. All compiled with g++. Wherever I have C headers I have the contents of the header file included inside
#if defined(__cplusplus)
extern "C" {
#endif
and
#if defined(__cplusplus)
extern "C" {
#endif
But in one C header file I get g++ compilation errors where I have accidentally used a parameter name as template , which obviously is incorrect and in conflict with c++ keyword template.
I know I can go and change this parameter name, but I am thinking why is this extern "C" declaration not working and why is the header file considered as C++ code and not C as I intended to.
g++ version 4.1.1 Linux Red Hat Enterprise.
The extern "C" only tells the compiler (actually, the linker) that C++ name mangling doesn't apply to the functions declared in that scope. It has nothing to do with the syntax or keywords themselves.
Your best solution is to rename the conflicting symbols.
Consider:
extern "C" {
namespace n
{
int& foo(bool b)
{
if (!b)
throw std::invalid_argument("fail!");
static int i = 0;
return ++i;
}
}
}
This function has C language linkage, but uses references, namespaces and exceptions, which I hope demonstrates that extern "C" doesn't magically switch the compiler to compiling C, it just tells the compiler to use C calling conventions and symbol-naming conventions for the functions and variables with C language linkage (which usually just means it disables name-mangling and causes matching declarations in different namespaces to refer to the same entity.)

C linkage and c++ headers

I want to use some c++ classes in shared library with C linkage. And i got following problems.
If
#include <iostream>
extern "C"
{
void f(){}
}
Compiles and links succesfully, but f() could not be found in resulting library.
If
extern "C"
{
#include <iostream>
void f(){}
}
I got many compiler errors (just dont know how to correctly translate them in english, something about template with C linkage) on every occurence of C++ keyword "template" in iostream and included headers.
What should be done?
The first variant is correct. Only stuff that even exists in C can be declared in a extern "C" block, and templates and classes certainly don't belong in that category. You only have to make sure, that your function is also declared as extern "C" in the header if you are using a C++-compiler. This is often achieved by writing
#ifdef __cplusplus
// C++ declarations (for example classes or functions that have C++ objects
// as parameters)
extern "C"
{
#endif
// C declarations (for example your function f)
#ifdef __cplusplus
}
#endif
in the header.
The first is correct; system headers (and most other headers as well)
can only be included at global scope, outside any namespaces, classes,
functions or linkage specification blocks. There are likely things in
<iostream> that wouldn't be legal in an extern "C", and even if
there weren't, the name mangling for extern "C" is almost certainly
different from that of C++, and the library itself was surely compiled
as extern "C++".
How did you define f? This could be a similar problem: if the source
file compiles it as an extern "C++" function, then the name will be
mangled differently than it was in the client files which compiled it as
an extern "C" function.
The general policy here is to handle the headers and the function
definitions/declarations in the same way you normally do, except that
you ensure that the header can be included in both C and C++ sources,
e.g.:
#if __cplusplus
extern "C" {
#endif
void f();
// Other `extern "C"` functions...
#if __cplusplus
}
#endif
Then include this header in all files where the function f() is used,
and in the file where it is defined.
Use __declspec to export functions, classes, etc...
Also: http://msdn.microsoft.com/en-us/library/a90k134d(v=vs.80).aspx
And this one is very good: http://www.flounder.com/ultimateheaderfile.htm