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.
Related
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
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
In my project there are 3 possible types of files: pure C/Objective-C, pure C++ or Objective-C++ code.
How to divide functions in .h file with #define directives into parts to make this file available for all these files? I don't want to rename all the .m files to .mm because of problems with refactoring.
I know that I can write .h file in C which uses C++ .cpp file using the following code:
#ifndef Chadstone_CCCWrapper_h
#define Chadstone_CCCWrapper_h
#ifdef __cplusplus
#include <string.h>
extern "C"
{
#endif
void minMaxCoordinates(char *c, float *minX, float *minY, float *maxX, float *maxY);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
but what if I want to add functions with using of NSString or list<...>.
You can find it in standard pch-file genarated by Xcode:
#ifdef __OBJC__
#endif
Also you need use CF_EXPORT macro when declaring function to prevent linkage errors.
Example:
#ifndef SOME_H_FILE
#define SOME_H_FILE
#ifdef __OBJC__
#interface SomeObjClass: NSObject
#end
CF_EXPORT void SomeFunctionWithNSString(NSString* str);
#endif
#ifdef __cplusplus
class SomeCPlusPlustClass
{
};
CF_EXPORT void someFunctionWithList(const list<int>& intList);
#ifdef __OBJ__
CF_EXPORT void someComplicatedFunction(NSString* str, const list<int>& intList);
#endif
#endif
CF_EXPORT void someFunction();
typedef struct _SomeStruct
{
} SomeStruct;
#endif
I've defined the following header file (in C), left out the function implementation since thise aren't needed:
#ifndef FFMPEG_MEDIAMETADATARETRIEVER_H_
#define FFMPEG_MEDIAMETADATARETRIEVER_H_
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
int setDataSource(AVFormatContext** pFormatCtx, const char* path);
#endif /*FFMPEG_MEDIAMETADATARETRIEVER_H_*/
In C++, I defined my second header file:
#ifndef MEDIAMETADATARETRIEVER_H
#define MEDIAMETADATARETRIEVER_H
using namespace std;
extern "C" {
#include "ffmpeg_mediametadataretriever.h"
}
class MediaMetadataRetriever
{
public:
MediaMetadataRetriever();
~MediaMetadataRetriever();
int setDataSource(const char* dataSourceUrl);
};
#endif // MEDIAMETADATARETRIEVER_H
In, mediametadataretriever.cpp I defined the following function:
int MediaMetadataRetriever::setDataSource(
const char *srcUrl)
{
// should call C function
AVFormatContext* pFormatCtx;
return setDataSource(&pFormatCtx, srcUrl);
}
When I try to compile this (C++) project in Eclipse I get a "No matching function call..." error related to:
return setDataSource(&pFormatCtx, srcUrl);
If I comment out the call, the code compiles fine:
int MediaMetadataRetriever::setDataSource(
const char *srcUrl)
{
return 0;
}
This appears to be a linking issue, does anyone know what I'm doing wrong?
setDataSource in that context is the name of the member function. To invoke the free function, try fully qualifying its name:
return ::setDataSource(&pFormatCtx, srcUrl);
// ^^
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