如何从C语言中调用C++函数?

问题描述 投票:1回答:2

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

所以,api提供了以下目录,我把它放在了一个叫include的文件夹里,和我的makefile处于同一级别。

libmyapi.a
api/api.h

我的主源文件是srcmyapp.c, 它包含了api,使用了 #include "api/api.h".

我的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'"来 "包装 "代码,但我不太明白。 在网上看了一圈,我没有任何进一步的了解。

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

我是否需要 "封装 "代码,那是什么意思?我是否只需要做

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

还是我只需要把这几行字包起来

namespace MyAPI {
      namespace API {

然后再调用它们对应的}}?

头文件会调用其他头文件,所以有可能我需要在相当多的地方这样做。

到目前为止,我试过的所有变化都出现了错误和警告,但我不知道是我的封装做错了,还是g++编译器标志设置错了,还是使用了错误的编译器,还是什么!如果我知道使用的方法,我至少可以开始调试。如果我知道该用什么方法,至少可以开始调试了。 谢谢你!我在写一个C语言程序(C++编译器)。

c++ c makefile
2个回答
7
投票

你可以写一个小的C++程序,为api创建一个C的绑定。

Gvien这个API。

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

你可以创建c_api.

#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++编译器创建的库和原始库。


5
投票

基本上,你的C++库需要导出一个纯C的API。也就是说,它必须提供一个完全依赖于的接口。typedef, struct, enum,预处理器指令宏(也许还有一些我忘了说的东西,不过必须都是有效的C代码)。如果没有这样的接口,你就不能把C代码和C++库连接起来。

这个纯C API的头需要既可以用C语言编译器又可以用C++编译器编译,但是,当你把它编译成C++时,你必须告诉C++编译器这是一个C接口。这就是为什么你需要将整个API包裹在

extern "C" {
    //C API
}

当编译为C++时。然而,这根本不是C代码,所以你必须隐藏掉这个 extern "C" 的C编译器。这是通过添加预处理程序指令

#ifdef __cplusplus1
extern "C" {
#endif

    //C API

#ifdef __cplusplus1
}
#endif

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


3
投票

如何从C语言中调用C++函数?

通过编写调用函数,其声明在C和C++的通用子集中有效。并通过在C++中声明与C语言关联的函数。

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

这种头不是用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();
}

0
投票

你不能这样做 你可以在你的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". :)

© www.soinside.com 2019 - 2024. All rights reserved.