从"C"代码调用"C++"类成员函数

19

如何在“C”代码中调用“C ++”类成员函数?

我有两个文件 .cpp ,其中我定义了一些具有成员函数的类,并对应包含了一些其他帮助cpp / h文件的相应 .h 文件。

现在我想在 C 文件中调用这些CPP文件的功能。我该怎么做?

1个回答

36

C语言没有 thiscall 的概念。C调用约定不允许直接调用C++对象的成员函数。

因此,您需要提供一个围绕您的C++对象的包装器API,该API显式地接受this指针,而不是隐式地传递它。

例如:

// C.hpp
// uses C++ calling convention
class C {
public:
   bool foo( int arg );
};

C包装器API:

// api.h
// uses C calling convention
#ifdef __cplusplus
extern "C" {
#endif

void* C_Create();
void C_Destroy( void* thisC );
bool C_foo( void* thisC, int arg );

#ifdef __cplusplus
}
#endif

你的API将使用C++实现:

#include "api.h"
#include "C.hpp"

void* C_Create() { return new C(); }
void C_Destroy( void* thisC ) {
   delete static_cast<C*>(thisC);
}
bool C_foo( void* thisC, int arg ) {
   return static_cast<C*>(thisC)->foo( arg );
}

有很多优秀的文档可供参考。 我最先发现的文档是这里,你也可以在这里找到。


@Priyanshu:有趣的转折。C语言不支持虚函数,但你的API代码却支持。所以,如果D覆盖(虚拟)foo函数,你只需要额外添加一个D_Create在API中。我认为这很像工厂模式。但也许你需要提供更具体的信息。 - xtofl
2
@Priyanshu:C++中的任何指向对象的指针都需要在API函数中转换为void*。因此,对于API中所需的任何类,您都需要一组C包装器函数。当然,您会尝试尽可能保持API尽可能小,这可能会引起一些重新思考... - xtofl
2
@xtofl:不一定需要一个 void*,你可以为此目的前向声明一个 struct,在 C++ 中为每个类使用不同的 struct。或者更可能是为每个基类在 C++ 中使用不同的 struct,因为 C 无法处理多态性。 - Steve Jessop
@Priyanshu:你确实可以实现这个,但那样你就是在C语言中实现面向对象支持。我认为你需要的是1.一个“创建”函数,和2.提供访问你的类实现的接口的函数。但我认为你在评论中真正询问的是另一个问题。 - xtofl
@Priyanshu 在C++中,结构体和类之间没有太大的语义差异。只是默认访问模式不同:如果省略访问说明符,则结构体假定为public,而类则假定为private。您可以使用“struct C”而不是“void”:这更具描述性,并且是C中常见的PIMPL用例。 - Red.Wave
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接