Instead of writing each function in " extern "C" {} ", can I write entire header file inside that block.
extern "C"
{
#include "myCfile.h"
}
I have tried this but Its not working at all, why it is not working ?
if we have to use 100 C functions in a c++ project, do we need provide all the functions in a
extern block, is there any other simple way ?
Ex:
extern "C"
{
void fun1();
void fun2();
void fun3();
void fun4();
void fun5();
.
.
.
.
fun100();
}
Is there any other simple way, like extern "C" { myCfunctions.h } ???
#include simply includes the specified header at the location of the #include. Whether it's valid depends on what "myCfile.h" contains. In particular, including any standard library headers in such a context is not valid, and may well break on commonly used implementations.
The usual way to handle this is to make the header itself safe to use from C++. A C-only header might contain
#ifndef H_MYCFILE
#define H_MYCFILE
#include <stddef.h>
void mycfunc1(void);
void mycfunc2(int i);
void mycfunc3(size_t s);
#endif
Adapting this to make it safe to use from C++:
#ifndef H_MYCFILE
#define H_MYCFILE
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void mycfunc1(void);
void mycfunc2(int i);
void mycfunc3(size_t s);
#ifdef __cplusplus
}
#endif
#endif
With such a header, you wouldn't be able to safely put the entire header in an extern "C" block. However, that header itself can make sure not to put #include <stddef.h> in an extern "C" block, but still to put all function declarations in a single extern "C" block, avoiding having to repeat it for each one.
You are doing something wrong.
Because
extern "C" { myCfunctions.h }
should work. See below sample program.
Lets go by example code.
ctest1.c
#include<stdio.h>
void ctest1(int *i)
{
printf("This is from ctest1\n"); // output of this is missing
*i=15;
return;
}
ctest2.c
#include<stdio.h>
void ctest2(int *i)
{
printf("This is from ctest2\n"); // output of this is missing
*i=100;
return;
}
ctest.h
void ctest1(int *);
void ctest2(int *);
Now lets make c library from that
gcc -Wall -c ctest1.c ctest2.c
ar -cvq libctest.a ctest1.o ctest2.o
Now lets make cpp based file which will use this c apis
prog.cpp
#include <iostream>
extern "C" {
#include"ctest.h"
}
using namespace std;
int main()
{
int x;
ctest1(&x);
std::cout << "Value is" << x;
ctest2(&x);
std::cout << "Value is" << x;
}
Now lets compile this c++ program with C library
g++ prog.cpp libctest.a
Output is :
Value is15Value is100
Related
I have these three source files:
test.h
#ifndef __TESTH
#define __TESTH
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef struct {
uint8_t value;
} my_struct;
EXTERNC void initialise();
EXTERNC void load(my_struct**);
#endif
test.cpp:
#include <cstdint>
#include "test.h"
my_struct test;
void initialise() {
test.value = 200;
}
void load(my_struct** struct_ptr) {
*struct_ptr = &test;
}
main.cpp:
#include <cstdint>
#include <iostream>
#include "test.h"
my_struct *test;
int main() {
initialise();
load(&test);
while (true) {
std::cout << test->value << std::endl;
}
}
When I compile it, the linker gives me an error telling me that test has been defined multiple times (first defined in test.cpp).
Why? To me it seems like it doesn't leave the scope of test.cpp.
And when I remove the definition of test in main.cpp, it gives me an undefined error!
Thank you for taking the time out of your day to help me.
I think you would need to scope test.cpp's test variable to that file only, assuming your test pointer in main.cpp is different than test in test.cpp
namespace {
my_struct test;
}
See here
This question already has answers here:
What is the effect of extern "C" in C++?
(17 answers)
Including C headers inside a C++ program
(5 answers)
Closed 5 years ago.
file1.c
int add(int a, int b)
{
return (a+b);
}
file2.cpp
void main()
{
int c;
c = add(1,2);
}
h1.h
extern "C" {
#include "stdio.h"
int add(int a,int b);
}
Case 1:
when i include h1.h in file1.c file then gcc compiler throw an error "expected '(' before string constant".
case 2:
when I include h1.h in file2.cpp file compilation work successfully
Question:
1) Does it mean that I can not include header file in C with extern "C" function in it??
2) Can I include header within extern"C" like shown below
extern "C" {
#include "abc.h"
#include "...h"
}
3) Can I put c++ functions definitions in header file with extern "C" so that i can call it in C file?
for example
a.cpp ( cpp file)
void test()
{
std::printf("this is a test function");
}
a.h (header file)
extern "C" {
void test();
}
b_c.c ( c file)
#include "a.h"
void main()
{
test();
}
Write a.h like this:
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
int add(int a,int b);
#ifdef __cplusplus
}
#endif
This way you can declare multiple functions - there is no need to prefix each one with extern C.
As others mentioned: extern C is a C++ thing, so it needs to "disappear" when seen by C compiler.
Since extern "C" is not understood by a C-compiler you need to create a header that can both be included in a C and C++ file.
E.g.
#ifdef __cplusplus
extern "C" int foo(int,int);
#else
int foo(int,int);
#endif
I have a Xcode project with Swift and C++ (with bridging header), and I am trying to create a function in C++ with 2 string parameters, and returning an array of integers back to Swift:
.cpp file:
int* example(string one, string two)
{
int test[3] = {7,2,3};
return test;
}
.h file:
#if __cplusplus
extern "C" {
#endif
int* example(string one, string two); //ERROR HERE
#ifdef __cplusplus
}
#endif
I am getting this error (in the .h file):
Unknown type name 'string'
I tried to include the string header file to the header, but then I get the error (I also had to add std:: before the string):
New function declaration:
int* example(std::string one, std::string two);
Error (at the first std::)
Expected ')'
I am really losing my patience here, what am I doing wrong?
You can't use class types in extern "C" declaration. You can introduce the following trick:
header:
#if __cplusplus
extern "C" {
#endif
int* example(void *one, void *two);
#ifdef __cplusplus
}
#endif
source: (.cpp assumed)
#include <string>
using namespace std;
extern "C" {
int* example(void *one, void *two)
{
string &a = *reinterpret_cast<string*>(one);
string &b = *reinterpret_cast<string*>(two);
...
}
}
You must pass strings by ptr.
Contents of somefile.h:
#ifndef __SOMEFILE_H
#define __SOMEFILE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _table_t
{
void (*somefunction1)();
void (*somefunction2)(int a);
void (*somefunction3)(int a, int *b);
}table_t;
void doSomething1();
void doSomething2();
#ifdef __cplusplus
} // error at this line: expected constructor, destructor, or type conversion before '(' token
#endif
#endif
Shown above is the code snippet and the error I get when I compile my code on Linux. The same code compiles fine on Windows with no complaints.
About the source file:
all.h is a header file which includes:
#include "header1.h"
#include "header2.h"
#include "header3.h"
#include "somefile.h"
Here is the content of somefile.c
#include "all.h"
#include "header4.h"
jumptable_t jumptable_a =
{
a_function1();
a_function2(int a);
a_function3(int a, int *b);
}
//more code
void function1()
{
a_function1();
}
void function2(int a)
{
a_function2(a);
}
void function3(int a, int *b)
{
a_function3(a, b);
}
void doSomething1()
{
}
void doSomething2()
{
}
Macro with leading double underscores is illegal. You need to change your include guard.
You need a ; after the } of jumptable_a. And use commas instead of semicolons in the initializer of jumptable_a.
The braces make it look like a somethink function-like, but it's not.
Also, in somefile.h the struct is called table_t, but in somefile.c you are using jumptable_t, which I assume is an error introduced when writing the post here.
We have a large project with C and C++ code.
For every C++ implementation, apart from the C++ header, we usually have provide a C-header to allow functionality to be available for .c files, also.
So, most of our files look like so:
foo.hpp:
class C {
int foo();
};
foo.h:
#ifdef __cplusplus
extern "C" {
typedef struct C C; // forward declarations
#else
class C;
#endif
int foo( C* ); // simply exposes a member function
C* utility_function( C* ); // some functionality *not* in foo.hpp
#ifdef __cplusplus
}
#endif
foo.cpp:
int C::foo() { /* implementation here...*/ }
extern "C"
int foo( C *p ) { return p->foo(); }
extern "C"
C* utility_function ( C* ) { /* implementation here...*/ }
QUESTION:
Suppose I wanted to add a namespace to the class like so:
foo.hpp:
namespace NS {
class C {
int foo();
};
}
what is the best scheme to follow in the C-headers?
I have considered a few options, but I'm looking for the most elegant, safe and easy to read. Is there a standard way you use?
Here are the options I've considered:
(I've ommitted the extern "C" constructs for simplicity)
Option 1: fool the compiler by adding some code in each header:
foo.h
#ifdef __cplusplus
namespace NS { class C; } // forward declaration for C++
typedef NS::C NS_C;
#else
struct NS_C; // forward declaration for C
#endif
int foo( NS_C* );
NS_C* utility_function( NS_C* );
this adds some complexity to the header, but keeps the implementations unchanged.
Option 2: Wrap the namespace with a C-struct:
Keeps the header simple but makes the implementation more complex:
foo.h
struct NS_C; // forward declaration of wrapper (both for C++ and C)
int foo( NS_C* );
NS_C* utility_function( NS_C* );
foo.cpp
namespace NS {
int C::foo() { /* same code here */ }
}
struct NS_C { /* the wrapper */
NS::C *ptr;
};
extern "C"
int foo( NS_C *p ) { return p->ptr->foo(); }
extern "C"
NS_C *utility_function( NS_C *src )
{
NS_C *out = malloc( sizeof( NS_C ) ); // one extra malloc for the wrapper here...
out->ptr = new NS::C( src->ptr );
...
}
are these the only schemes? Are there any hidden disadvantages in any of these?
I find it easier to factor code in a way so that foo.h only contains the bare minimum of C++ specifics while foo.hpp takes care of the gritty bits.
The file foo.h contains the C API and should not be included directly from C++ code:
#ifndef NS_FOO_H_
#define NS_FOO_H_
// an incomplete structure type substitutes for NS::C in C contexts
#ifndef __cplusplus
typedef struct NS_C NS_C;
#endif
NS_C *NS_C_new(void);
void NS_C_hello(NS_C *c);
#endif
The file foo.hpp contains the actual C++ API and takes care of including foo.h into C++ files:
#ifndef NS_FOO_HPP_
#define NS_FOO_HPP_
namespace NS {
class C {
public:
C();
void hello();
};
}
// use the real declaration instead of the substitute
typedef NS::C NS_C;
extern "C" {
#include "foo.h"
}
#endif
The implementation file foo.cpp is written in C++ and thus includes foo.hpp, which also pulls in foo.h:
#include "foo.hpp"
#include <cstdio>
using namespace NS;
C::C() {}
void C::hello() {
std::puts("hello world");
}
C *NS_C_new() {
return new C();
}
void NS_C_hello(C *c) {
c->hello();
}
If you do not want to make the C API available to C++ code, you could move the relevant parts from foo.hpp to foo.cpp.
As an example for use of the C API a basic file main.c:
#include "foo.h"
int main(void)
{
NS_C *c = NS_C_new();
NS_C_hello(c);
return 0;
}
This example has been tested with the MinGW edition of gcc 4.6.1 using the following compiler flags:
g++ -std=c++98 -pedantic -Wall -Wextra -c foo.cpp
gcc -std=c99 -pedantic -Wall -Wextra -c main.c
g++ -o hello foo.o main.o
The code assumes that the types NS::C * and struct NS_C * have compatible representation and alignment requirements, which should be the case virtually everywhere, but as far as I know is not guaranteed by the C++ standard (feel free to correct me if I'm wrong here).
From a C language perspective, the code actually invokes undefined behaviour as you're technically calling a function through an expression of incompatible type, but that's the price for interoperability without wrapper structures and pointer casts:
As C doesn't know how to deal with C++ class pointers, the portable solution would be to use void *, which you should probably wrap in a structure to get back some level of type safety:
typedef struct { void *ref; } NS_C_Handle;
This would add unnecessary boilerplate on platforms with uniform pointer representation:
NS_C_Handle NS_C_new() {
NS_C_Handle handle = { new C() };
return handle;
}
void NS_C_hello(NS_C_Handle handle) {
C *c = static_cast<C *>(handle.ref);
c->hello();
}
On the other hand, it would get rid of the #ifndef __cplusplus in foo.h, so it's actually not that bad, and if you care about protability, I'd say go for it.
I don't fully understand what you're trying to do, but this may help:
If you want it still accessible by C then do this:
void foo();
namespace ns {
using ::foo;
}
Or use a macro:
#ifdef __cplusplus
#define NS_START(n) namespace n {
#define NS_END }
#else
#define NS_START(n)
#define NS_END
#endif
NS_START(ns)
void foo();
NS_END
Your header is all messed up.
You probably want something more like:
struct C;
#ifdef __cplusplus
extern "C" {
#else
typedef struct C C;
#endif
/* ... */
#ifdef __cplusplus
}
#endif