在C应用程序中运行C++(带有STL)函数
Running C++ (with STL) functions in a C application
我正在创建一个C++库,其中包含使用某些STL功能的导出C函数。我想把这个库包含在C应用程序中。
我已经尽我所能将这个问题简化为以下4个文件。
main.c
#include "aaa.h"
#include <stdio.h>
int main()
{
printf("Version: %u.%un", GetAPIMajorVersion(), GetAPIMinorVersion());
return 0;
}
aaa.h
#ifndef AAA_H
#define AAA_H
#ifdef __cplusplus
#define DllExport extern "C"
#else // __cplusplus
#define DllExport
#endif // __cplusplus
#include <stdint.h>
DllExport uint32_t GetAPIMajorVersion();
DllExport uint32_t GetAPIMinorVersion();
#endif // AAA_H
aaa.cpp
#include "aaa.h"
#include <string>
#include <vector>
// Builds and works fine.
uint32_t GetAPIMajorVersion()
{
std::string val = "hello world";
return val.size();
}
// Produces the error messages
uint32_t GetAPIMinorVersion()
{
std::vector<bool> test;
test.push_back(true);
return test.size();
}
我正在使用以下脚本来构建库和应用程序。
build.sh
# Build the C++ library
g++ -m64 -Wall -O3 -c -fmessage-length=0 -fPIC -MMD -MP aaa.cpp -o aaa.o
ar rcs libaaa.a aaa.o
# Build the executable
gcc -m64 -Wall -static main.c -o main -L./ -laaa
当我尝试构建C应用程序时,我得到了以下错误
.//libaaa.a(aaa.o): In function `GetAPIMinorVersion':
aaa.cpp:(.text+0xeb): undefined reference to `operator delete(void*)'
aaa.cpp:(.text+0x1c7): undefined reference to `operator delete(void*)'
.//libaaa.a(aaa.o): In function `std::vector<bool, std::allocator<bool> >::_M_insert_aux(std::_Bit_iterator, bool)':
aaa.cpp:(.text._ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb[_ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb]+0x1d8): undefined reference to `operator new(unsigned long)'aaa.cpp:(.text._ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb[_ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb]+0x339): undefined reference to `operator delete(void*)'
aaa.cpp:(.text._ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb[_ZNSt6vectorIbSaIbEE13_M_insert_auxESt13_Bit_iteratorb]+0x3cb): undefined reference to `std::__throw_length_error(char const*)'.//libaaa.a(aaa.o):(.data.DW.ref.__gxx_personality_v0[DW.ref.__gxx_personality_v0]+0x0): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status
我查看了这个错误,这似乎是因为C应用程序无法访问STL库,但如果我们更改main.C,只调用GetAPIMajorVersion()
并从库中删除GetAPIMinorVersion()
函数。应用程序按预期编译和运行。
这让我相信问题不在于STL库,而在于STL库中的一些函数。
我的下一个猜测是,std::vector<bool>::push_back()
函数可能会抛出一个异常,这就是在aaa.a库中包含C应用程序找不到的元素。
如果这是问题所在,我该如何在aaa.a库中包含STL库的必需部分,以便C应用程序可以使用它?
我发现,如果我将C应用程序更改为使用g++
而不是gcc
构建,它就会构建并运行良好。不幸的是,我最终使用的编译器只支持C99,这对我来说不是一个选项
g++ -m64 -Wall -static main.c -o main -L./ -laaa
我应该如何构建这个包含STL函数的库,以使库函数可以从C应用程序中调用?
编辑
- 我最后使用的编译器是Arm-Keil
- 似乎没有将
stdc++
作为库包含在Arm-Keil IDE/编译器中的选项。据我所知,我无法将构建C应用程序的命令更改为gcc -m64 -Wall -static main.c -o main -L./ -laaa -lstdc++
您可以尝试构建一个C++共享库,链接-lstdc++
。
因此,让-laaa
是一个共享库libaaa.so
(来自源文件aaa1.cc
和aaa2.cc
,具有独立于位置的代码(,您将使用它来构建:
g++ -fPIC -O3 -g aaa1.cc -o aaa1.pic.o
g++ -fPIC -O3 -g aaa2.cc -o aaa2.pic.o
g++ -fPIC -shared -O3 -g aaa1.pic.o aaa2.pic.o -lstdc++ -o libaaa.so
你也可以设置一些rpath。
阅读程序库如何和Drepper的如何编写共享库
我最后使用的编译器是Arm-Keil
您最好使用一些GCC交叉编译器(或Clang编译器(的最新版本。要么你自己用GCC 8的源代码构建交叉编译器(2018年秋季(,要么在Linux发行版上安装一些交叉编译器。例如,Debian/Sid有gcc-8-arm-linux-gnueabi
和gcc-8-arm-linux-gnueabihf
根据经验,硬件供应商提供古老的交叉编译器(在软件工程方面并不好(。这就是为什么我建议在命令行上使用最新的GCC交叉编译器。
您将更好地将您的应用程序与g++
链接起来。
我的下一个猜测是,std::vector::push_back((函数可能会抛出异常
异常需要crt0级别的一些支持(对于std::terminate(。如果您的库抛出一些异常,则主程序必须与g++
链接(如果您想要一个可从C中使用的C++库,则不应在外部抛出异常(。
但是,需要注意的是,可以从gcc
编译的C代码中构建一个可用的C++库。libgccjit就是这样一个库(但它不会在外部抛出异常(。
我无法将构建C应用程序的命令更改为gcc-m64-Wall-static main.C-o main-L。/-laaa-lstdc++据我所知
你当然可以。您需要避免使用Arm-Kell,而是直接在命令行上使用适当的交叉编译器(可以是其中提供的交叉编译器,也可以是从GCC源代码或Clang-one构建的最新交叉编译器(。
- 在C应用程序中运行C++(带有STL)函数
- 使用 STL 仅保留 N 个最小元素(带有重复项)
- 使用带有COM接口的STL智能指针
- 带有原始指针的stl::迭代器
- 为什么Visual Studio 2015在Juce存在时无法编译带有"noexcept"的STL库?
- 使用带有私有构造函数的类的STL容器(再次)
- 从给定的STL容器中提取带有给定谓词的元素到另一个容器
- 带有内存比较的 STL 映射.如何在运行时设置比较块大小
- 带有 STL 向量的模板函数会因新的分配器而中断
- stl::map 插入一个带有约束的值
- 如何在 c++ 中使用 STL 将带有空格的字符串连接成一个字符串
- 如何避免内存泄漏,使用带有STL容器的C++
- C++ replace_if在 STL 中带有结构的向量上
- 带有结构的STL地图
- 带有 STL 映射的 STL 对输入
- UTF-8到带有STL的本地多字节
- 对于具有线性存储的容器,可以使用原始指针代替带有STL算法的迭代器吗?
- 带有STL容器的c++函数模板特化
- 带有STL c++ bug的强连接组件
- 从共享库调用带有STL参数的函数