Я создаю библиотеку C ++ с экспортированными функциями C, которые используют некоторые функции STL. Я хочу включить эту библиотеку в C-приложение.
Я максимально уменьшил проблему до следующих 4 файлов.
main.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()
может выдать исключение, и это включает элементы в библиотеку aaa.a, которую приложение C не может найти.
Если это проблема, то как мне включить обязательные части библиотеки STL в библиотеку aaa.a, чтобы она могла использоваться приложением C?
Я обнаружил, что если я изменяю приложение C для сборки с g++
вместо gcc
, оно собирается и работает нормально. К сожалению, компилятор, который я использую в конце концов, поддерживает только C99, и это не вариант для меня.
g++ -m64 -Wall -static main.c -o main -L./ -laaa
Как мне построить эту библиотеку, которая включает функции STL, таким образом, чтобы функции библиотеки можно было вызывать из приложения C?
Редактировать
- В конце я использую компилятор Arm Keil
- Похоже, нет возможности включить
stdc++
в качестве библиотеки в IDE / компилятор Arm Keil. Насколько мне известно, я не могу изменить команду для сборки приложения C на gcc -m64 -Wall -static main.c -o main -L./ -laaa -lstdc++
.