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

rnmwe5a2  于 2023-06-21  发布在  其他
关注(0)|答案(4)|浏览(168)

我正在写一个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编译器进行编译,但后来有人说我不需要,我可以用“extern 'C'”来“ Package ”代码,但我真的不明白。我在网上看了一下,没有进一步的进展。
我需要用C
编译吗(即使用g++)?
我需要“ Package ”代码吗?这意味着什么?我只是做:

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

还是把台词绕起来

namespace MyAPI {
      namespace API {

然后是它们对应的
头文件调用其他头文件,所以可能我需要在很多地方这样做。
到目前为止,我已经得到了错误和警告,我已经尝试了所有的变化,但我不知道我是否做了错误的 Package ,设置g++编译器标志错误,使用错误的编译器,或什么!如果我知道要使用的方法,我至少可以开始调试。

nuypyhwy

nuypyhwy1#

您可以编写一个小的C++程序,为API创建一个C绑定。
Gvien this 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_api. h文件包含在C项目中,并链接到使用C编译器创建的库和原始库。

uqzxnwby

uqzxnwby2#

基本上,您的C库需要导出纯C API。也就是说,它必须提供一个仅依赖于typedefstructenum、预处理器指令/宏的接口(可能还有一些我忘记提到的东西,但它们必须都是有效的C代码)。如果没有这样的接口,就无法将C代码与C库链接起来。
这个纯C API的头文件需要可以用C和C编译器编译,但是,当你将它编译为C时,你必须告诉C++编译器它是一个C接口。这就是为什么您需要将整个API Package 在

extern "C" {
    //C API
}

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

#ifdef __cplusplus1
extern "C" {
#endif

    //C API

#ifdef __cplusplus1
}
#endif

如果你不能改变你的库头,你需要创建一个 Package 器API来提供这个纯C API,并通过调用相应的C++代码。

b09cbbtk

b09cbbtk3#

如何从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();
}
mfuanj7w

mfuanj7w4#

你可以在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"。:)

相关问题