如何从C调用C++函数

How do I call C++ functions from C?

本文关键字:C++ 函数 调用      更新时间:2023-10-16

我正在编写一个C程序(myapp),该程序需要使用特定的API;API是用C++编写的。我曾经使用过C和C++,但从来没有同时使用过这两种语言,我很困惑。

因此,API提供了以下目录,我将其放在名为include的文件夹中,与我的makefile处于同一级别:

libmyapi.a
api/api.h

我的主要源文件是src/myapp.c,其中包括使用#include "api/api.h"的API。

我的make命令是(加上一些标志,我没有列出,因为我认为它们在这里不相关):

gcc  -Linclude -lmyapi -Iinclude  src/myapp.c -o lib/myapp.sp -lrt

我遇到的问题是api.h文件包含对名称空间等的引用

namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}

显然C编译器不知道这意味着什么。

所以,我认为我需要使用C++编译器进行编译,但后来有人说我没有,我可以"包裹";";外部"C";,但我真的不明白。在网上阅读了之后,我不再继续了。

我需要用C++编译吗?

我需要";"包裹";代码,这意味着什么?我只是这样做吗:

#ifdef __cplusplus
extern "C" {
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
}
#endif

还是我把线包起来

namespace MyAPI {
namespace API {

然后它们对应的}}?

头文件调用其他头文件,所以我可能需要在很多地方这样做。

到目前为止,我尝试过的所有变体都有错误和警告,但我不知道我是包装错误、设置g++编译器标志错误、使用错误的编译器,还是什么!如果我知道要使用的方法,我至少可以开始调试。

您可以编写一个小型C++程序,为API创建C绑定。

查看此API:

namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}

您可以创建c_api.h

#ifdef __cplusplus
extern "C" {
#endif
struct api_handle_t;
typedef struct api_handle_t* api_handle;
api_handle myapi_api_create();
void myapi_api_some_function_using_api(api_handle h);
void myapi_api_destroy(api_handle h);
#ifdef __cplusplus
}
#endif

和c_api.cpp

#include "c_api.h"
#include <myapi/api/stuff.hpp>
struct api_handle_t
{
MyAPI::API::SimpleConnection c;
};
api_handle myapi_api_create()
{
return new api_handle_t;
}
void myapi_api_some_function_using_api(api_handle h)
{ 
//implement using h
}
void myapi_api_destroy(api_handle h) 
{
delete h;
}

用C++编译器编译它,并在C项目中包含C_api.h文件,并链接到用C++编译器创建的库和原始库。

基本上,您的C++库需要导出纯C API。也就是说,它必须提供一个仅依赖于typedefstructenum、预处理器指令/宏的接口(也许还有一些我忘了提的事情,但它必须都是有效的C代码)。如果没有这样的接口,就无法将C代码与C++库链接起来。

这个纯C API的头需要与C和C++编译器都可编译,但是,当你将其编译为C++时,你必须告诉C++编译器它是一个C接口。这就是为什么您需要将整个API封装在中

extern "C" {
//C API
}

当编译为C++时。但是,这根本不是C代码,因此必须向C编译器隐藏extern "C"。这是通过添加预处理器指令来完成的

#ifdef __cplusplus1
extern "C" {
#endif
//C API
#ifdef __cplusplus1
}
#endif

如果无法更改库头,则需要创建一个包装器API,该包装器提供这种纯C API并调用相应的C++代码。

如何从C调用C++函数?

通过编写声明在C和C++的公共子集中有效的调用函数。并通过在C++中声明具有C语言链接的函数。

我遇到的问题是api.h文件包含对命名空间的引用

这样的头没有写在C和C++的公共子集中,因此它不能从C中使用。您需要写一个有效的C头才能在C中使用它。

我需要用C++编译吗(即使用g++)?

如果您有用C++编写的函数定义,那么您需要用C++编译器编译这些C++函数。如果您有C函数调用这些C++函数,那么您需要使用C编译器编译这些C函数。


一个最小的例子:

// C++
#include <iostream>
extern "C" void function_in_cpp() {
std::cout << "Greetings from C++n";
}
// C
void function_in_cpp(void);
void function_in_c(void) {
function_in_cpp();
}

您不能。您可以在C++程序中使用C函数。但是你不能使用C中的C++。当C++被发明时,它允许C函数的兼容性和重用,所以它被写为C的超集,允许C++调用所有C库函数。

但事实并非如此。当C被发明时,还没有定义C++语言。

调用C++函数的唯一方法是将整个项目转换为C++函数。。。您需要使用C++编译器(或者如果是纯C,则使用C编译器)编译C函数,但对于要调用C++函数的C函数,必须将其编译为C++。你应该用申报

extern "C" {
void my_glue_func(type1 param1, type2 param2, ...)
{
/* ... */
}
} /* extern "C" */

并将整个事情链接为C++程序(调用C++链接器)

这是因为C对函数重载类初始化实例构造函数调用等一无所知。因此,如果你甚至可以解开C++函数的名称,以便能够从C调用它们(你最好不要尝试这样做),它们可能会在未初始化的情况下运行,因此你的程序可能(最)会崩溃。

如果你的main()函数恰好是一个C函数,那么没有问题。C++的设计考虑到了这一点,因此main()被隐式地声明为extern "C"。:)