简体   繁体   English

我可以在导出到c的c ++函数中使用`bool`类型或不透明指针吗?

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

I am working on the API of a library I am writing. 我正在编写我正在编写的库的API。 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). 库本身将用c++编写,但API将使用extern "C"导出,以实现最佳的跨语言兼容性(稍后我将使用C#C++C和其他一些语言来使用此API)。
Obviously, the API can't include whole classes or other c++ specific features (like throwing exceptions), but my questions are: 显然,API不能包含整个类或其他c++特定的功能(比如抛出异常),但我的问题是:

  1. Can I use the bool type in the exported API? 我可以在导出的API中使用bool类型吗? After all, it is a POD. 毕竟,这是一个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? 如果是这样,我将如何在头文件中声明它们,以便可以从C代码中使用头文件?

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). Bool应该没问题,ABI和语言设计人员对这些事情要谨慎(例如,C ++的complex<double>和C的complex double明确设计为兼容)。 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. 请注意,如果设置了各种编译器标志或属性,我已经看到了ABI兼容性问题 - 例如,如果启用了结构打包,则bool在使用GCC 4.2的C和C ++中的大小不同。

  1. Can I use the bool type in the exported API? 我可以在导出的API中使用bool类型吗? After all, it is a POD. 毕竟,这是一个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 bool是一种特定于C ++的类型,如果你在头文件中使用它,那就不能在C中编译。另外标准没有指定如何实现bool,所以最好依靠从int到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. 通常接受的方法是将对象的生命周期封装在C ++库中,并提供一组操作对象的C函数。 Note, even if you somehow enable access to your class via the pointer, you would be stuck with name-mangling and calling convention 请注意,即使您以某种方式通过指针启用对类的访问,您仍会遇到名称修改和调用约定

I finally went ahead and tested it. 我终于继续进行测试了。 Here are the test programs: 以下是测试程序:

test_cpp.cpp: 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: 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: 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 在windows上使用mingw64 gcc-4.9.0进行编译

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 g++完全没有问题, C被声明为struct ,后来定义为class
  • c++ bool and c _Bool worked interchangeably c ++ boolc _Bool可互换使用

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 我尝试使用MS编译器(VS2012),除了一个我无法解释的小细节外,它的工作方式相同:在头文件中,我不得不改变

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. 如果有人能够解释这一点,我很乐意理解它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM