Can I use `bool` type or opaque pointers to classes in a c++ function exported to c?

StackOverflow https://stackoverflow.com/questions/23686409

  •  23-07-2023
  •  | 
  •  

Question

I am working on the API of a library I am writing. The library itself will be written in c++, but the API will be exported using extern "C" for best cross-language compatibility (I will be consuming this API later from C#, C++, maybe C and a few others).
Obviously, the API can't include whole classes or other c++ specific features (like throwing exceptions), but my questions are:

  1. Can I use the bool type in the exported API? After all, it is a POD.
  2. Can I use opaque pointers to classes? If so, how would I declare them in the header file so that the header file can be used from C code?
Was it helpful?

Solution 3

I finally went ahead and tested it. Here are the test programs:

test_cpp.cpp:

#include "test.h"

class C {
    int a;
public:
    C() : a(42) {}
    int  getA() { return a; }
    void setA(int v) { a=v; }
};

int get7(bool b) { return b ? 7 : 3; }

C c;
C* getC() { return &c; }
int  getA(C* t) { return t->getA(); }
void setA(C* t, int v) { return t->setA(v); }

test_c.c:

#include <stdio.h>
#include "test.h"

int main()
{
    C* c = getC();
    printf("%d\n", getA(c));
    setA(c, 10);
    printf("%d\n", getA(c));
    printf("%d\n%d\n%d\n%d\n", get7(0), get7(1), get7(2), get7(-1));

    return 0;
}

test.h:

#ifdef __cplusplus
extern "C" {
#else
#define bool _Bool
#endif

struct C;
typedef struct C C;

int get7(bool b);

C* getC();
int  getA(C* t);
void setA(C* t, int v);

#ifdef __cplusplus
}
#endif

Compiling with mingw64 gcc-4.9.0 on windows

gcc -c test_c.c
g++ test_cpp.cpp test_c.o

it compiled and ran correctly. Points of interest:

  • g++ had no problem at all with C being declared as a struct and later defined as a class
  • c++ bool and c _Bool worked interchangeably

I tried this with MS compiler (VS2012) and it worked the same except for one small detail that I can't explain: In the header file, I had to change

int get7(bool b);

to

int get7(bool);

to get it to compile. If anyone can explain this I would be happy to understand it.

OTHER TIPS

Bool should be fine, the ABI and language designers are careful about these things (complex<double> from C++ and complex double from C are explicitly designed to be compatible, for example). Classes can be turned into opaque pointers with forward declarations.

#ifdef __cplusplus
class MyClass;
#else
#include <stdbool.h>
typedef struct MyClass MyClass;
extern "C" {
#endif

bool IsActivated(MyClass *p, int x);

#ifndef __cplusplus
}
#endif

Note that I have seen ABI compatibility issues if various compiler flags or attributes are set—for example, bool is a different size in C and C++ using GCC 4.2 if structure packing is enabled.

  1. Can I use the bool type in the exported API? After all, it is a POD. bool is a C++ specific type and if you use it in your header file, that would not compile in C. Also standard does not specify how bool would be implemented, so it is better to rely on standard conversion from int to bool
  2. Can I use opaque pointers to classes? I am not sure what you would wan't to achieve here. The generally accepted approach is to encapsulate the lifetime of your object within your C++ library and provide a set of C functions that would manipulate the object. Note, even if you somehow enable access to your class via the pointer, you would be stuck with name-mangling and calling convention
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top