【问题标题】:Linking C program to C++ Shared Library将 C 程序链接到 C++ 共享库
【发布时间】:2014-09-08 11:45:11
【问题描述】:

我有一个用 C++ 编写的共享库,它也为用 C++ 编写的不同应用程序提供了一些 API 调用,现在我想在 C 程序中使用这个库。原始库包含仅对 C++ 有效的数据类型,例如 std::string 和 std::vector 如下:

typedef u_int32_t           ApplicationID;
typedef std::string         IPAddress;
typedef std::vector<int>    SDLIST;

这些数据类型被用作 API 的输入参数:

register_client(IPAddress ip);
export(ApplicationID id, SDLIST *list);

但是在C中,我们没有字符串也没有向量,这两种数据类型应该修改如下:

typedef char*   IPAddress;
typedef int*    SDLIST;

我尝试在我的代码中进行以下更改:

typedef u_int32_t           ApplicationID;
enter code here
#ifdef __cplusplus
    typedef std::string         IPAddress;
    typedef std::vector<int>    SDLIST;
#else
    typedef char*               IPAddress;
    typedef int*                SDLIST;
#endif


#ifdef __cplusplus
extern "C" {
#endif

    register_client(IPAddress ip);
    export(ApplicationID id, SDLIST *list);

#ifdef __cplusplus
}
#endif

我的问题是:

  1. 这是构建可用于 C 和 C++ 的库的正确方法吗?

  2. 我的共享库使用 Boost Interprocess 库,它是标准 POSIX 共享内存调用的包装器。每当我尝试将此共享库链接到任何应用程序时,我都应该在应用程序中再次包含lrt。所以我的问题是可以将共享库静态链接到lrt 库,而无需在所有使用我的共享库的应用程序中包含lrt

【问题讨论】:

  • 除非你也用 C 编译库,否则包含的头文件和底层定义将不匹配。相反,将接口更改为仅可 C 调用,或添加新标头和“包装”C++ 代码且可 C 调用的函数。
  • 为什么要用两种语言编写它?您可以创建一个 C 库并为其编写 C++ 绑定,或者编写一个 C++ 库并为其编写 C 绑定。然后将该库与您的应用程序链接,瞧。
  • DLL 的导出函数和数据类型应为 C 风格。

标签: c++ c boost shared-memory


【解决方案1】:

如果您想让它工作,您将需要构建一个 C++ 接口库,该库实现基于 C 的 API,将 C 数据类型转换为 C++ 数据类型。特别是 std::string 不是 char * 并且 vector 不是 int *。

例如,如果 API 定义了类似的 C++ 函数

bool CPPAPIFunction( std::string str, std::vector<int> vec )

你需要像这样实现一个包装函数(编译和链接为 C++)

int myCMappingFunction( char *cstr, int *carray, int arraylen )
{
    std::string str( cstr );
    std::vector<int> vec;
    for (int i =0; i < arraylen; i++ )  // ... copy C array into C++ vector
    return (int)CPPFAPIFunction( str, vec );
}

另外不要忘记在 extern "C" 块中声明你的包装函数,这样名称修饰将是 C 风格而不是 C++。

【讨论】:

    【解决方案2】:

    让我一一回答你的问题:

    1. 显然,根据您的用例,您想要混合什么样的代码。如果你想提供你的库应该可以从 C 和 C++ 调用的能力,你的库接口应该是 C 兼容的。查看 Using C++ library in C code 以获取有关如何将 C++ 函数包装在 C 接口中的答案。

    2. 通常建议您不要将库与所有依赖项一起打包,因为它会生成沉重的二进制文件并破坏共享库的目的,除非您打包的依赖项很小。但是,在您的情况下,如果您想这样做,您需要创建静态共享库。但是,无法从两个共享库创建。你需要他们两个的目标文件。请参阅Merge multiple .so shared libraries 以获得答案。

    【讨论】:

    • 感谢您的回答,但就我而言,我不希望应用程序知道我对共享内存的使用情况,这不是他关心的问题。
    • 是的..没错。为此,您需要实现包装函数来为您执行此操作。例如,您将需要具有接受和返回 C 数据类型而不是 C++ 数据类型的包装函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多