- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在创建一个 C++ 库,其中包含使用某些 STL 功能的导出 C 函数。我想将此库包含在 C 应用程序中。
我已将问题尽可能减少到以下 4 个文件。
主.c
#include "aaa.h"
#include <stdio.h>
int main()
{
printf("Version: %u.%u\n", 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()
可能是函数可能会抛出异常,这会将 C 应用程序找不到的元素包含到 aaa.a 库中。
如果这是问题所在,那么我如何将 STL 库的要求部分包含在 aaa.a 库中,以便 C 应用程序可以使用它?
我发现如果我将 C 应用程序更改为使用 g++
构建而不是 gcc
它构建并运行良好。不幸的是,我最终使用的编译器只支持 C99,这不是我的选择。
g++ -m64 -Wall -static main.c -o main -L./ -laaa
我应该如何以可以从 C 应用程序调用库函数的方式构建这个包含 STL 函数的库?
编辑
stdc++
的选项作为 Arm Keil IDE/编译器中的库。我无法将构建 C 应用程序的命令更改为 gcc -m64 -Wall -static main.c -o main -L./ -laaa -lstdc++
据我所知。 最佳答案
您可以尝试构建一个 C++ 共享 库,linking -lstdc++
.
所以让-laaa
成为一个共享库libaaa.so
(来自源文件aaa1.cc
和aaa2.cc
,并具有 position-independent code ),您将使用:
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 .
阅读Program Library HowTo和 Drepper 的 How to write shared libraries
The compiler that I am using at the end is Arm Keil
您最好使用一些最新 版本的 GCC交叉编译器(或 Clang 之一)。要么你自己从 GCC 8 的源代码构建那个交叉编译器(2018 年秋季),或者在 Linux 发行版上安装一些交叉编译器。例如,Debian/Sid 有 gcc-8-arm-linux-gnueabi
和 gcc-8-arm-linux-gnueabihf
根据经验,硬件供应商提供古老的交叉编译器(并且不擅长软件工程)。这就是为什么我建议在命令行上使用 最新 GCC 交叉编译器。
而且您最好将您的应用程序与 g++
链接起来。
My next guess is that it is possible that the std::vector::push_back() function could throw a exception
异常需要在 crt0 上得到一些支持级别(对于 std::terminate )。如果您的库抛出一些异常,则主程序必须链接 g++
(如果您想要一个可从 C 中使用的 C++ 库,它不应该在外部抛出异常)。
但是,只要小心,构建可从 gcc
编译的 C 代码中使用的 C++ 库是可能的。 libgccjit就是这样一个库(但它不会向外抛出异常)。
I can't change the command to build the C application to gcc -m64 -Wall -static main.c -o main -L./ -laaa -lstdc++ as far as I am aware
你当然可以。您需要避免使用 Arm Kell,并在命令行上直接使用适当的交叉编译器(它内部提供的交叉编译器,或者最好是您从 GCC 源代码或 Clang 构建的更新的交叉编译器)。
关于c++ - 在 C 应用程序中运行 C++(使用 STL)函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53110708/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!