运行 C++ 库在 iOS Xcode 项目中时出错

Error when running C++ libraries in iOS Xcode Project

我的 iOS Xcode 项目中有 C++ 文件。这些文件使用我通过 HomeBrew 调用的下一个库:

我将它们包含在项目中的方式是设置 HeaderSearch 路径:

以及库搜索路径:

这就是我调用这些库所做的全部工作。编译项目时遇到的错误是下一个:

Undefined symbols for architecture x86_64:
  "_mpg123_scan", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_mpg123_format_none", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_mpg123_length", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_mpg123_close", referenced from:
      MP3InputStream::close() in mp3inputstream.o
      MP3InputStream::detect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::ScopedMHandle::~ScopedMHandle() in mp3inputstream.o
  "_fftwf_plan_dft_r2c_1d", referenced from:
      fftar_float(unsigned long, float*, float*) in fft.o
  "_fftwf_free", referenced from:
      free_array_float(float*) in fft.o
  "_mpg123_read", referenced from:
      MP3InputStream::read_frames(std::__1::vector<float, std::__1::allocator<float> >&, unsigned long) in mp3inputstream.o
      MP3InputStream::detect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_fftwf_malloc", referenced from:
      new_array_float(unsigned long) in fft.o
  "_sf_readf_int", referenced from:
      SFInputStream::read_frames(std::__1::vector<float, std::__1::allocator<float> >&, unsigned long) in sfinputstream.o
  "_mpg123_open", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
      MP3InputStream::detect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_avformat_free_context", referenced from:
      HLSOutputStream::close() in hlsoutputstream.o
  "_mpg123_param", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
      MP3InputStream::detect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_avio_open", referenced from:
      HLSOutputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, unsigned long, double, unsigned long) in hlsoutputstream.o
  "_mpg123_delete", referenced from:
      MP3InputStream::close() in mp3inputstream.o
      MP3InputStream::detect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::ScopedMHandle::~ScopedMHandle() in mp3inputstream.o
  "_avformat_write_header", referenced from:
      HLSOutputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, unsigned long, double, unsigned long) in hlsoutputstream.o
  "_avcodec_free_context", referenced from:
      HLSOutputStream::close_stream() in hlsoutputstream.o
  "_swr_free", referenced from:
      HLSOutputStream::close_stream() in hlsoutputstream.o
  "_fftwf_plan_dft_c2r_1d", referenced from:
      fftsr_float(unsigned long, float*, float*) in fft.o
  "_swr_get_delay", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "_av_log", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "_mpg123_getformat", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
      MP3InputStream::detect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_av_frame_make_writable", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "_fftwf_execute_dft_r2c", referenced from:
      fftar_float(unsigned long, float*, float*) in fft.o
  "_av_rescale_rnd", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "_swr_convert", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "ff_decode(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, WavData&)", referenced from:
      _main in testhls.o
  "_avcodec_send_frame", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "_gcry_cipher_encrypt", referenced from:
      Random::seed(unsigned long long, Random::Stream) in random.o
      Random::refill_buffer() in random.o
  "_av_strerror", referenced from:
      av_make_error_string(char*, unsigned long, int) in hlsoutputstream.o
  "_avcodec_open2", referenced from:
      HLSOutputStream::open_audio(AVCodec*, AVDictionary*) in hlsoutputstream.o
  "_avio_closep", referenced from:
      HLSOutputStream::close() in hlsoutputstream.o
  "_av_dict_free", referenced from:
      HLSOutputStream::open_audio(AVCodec*, AVDictionary*) in hlsoutputstream.o
  "_swr_alloc", referenced from:
      HLSOutputStream::open_audio(AVCodec*, AVDictionary*) in hlsoutputstream.o
  "_sf_readf_float", referenced from:
      SFInputStream::read_frames(std::__1::vector<float, std::__1::allocator<float> >&, unsigned long) in sfinputstream.o
  "VResampler::VResampler()", referenced from:
      BufferedResamplerImpl<VResampler>::BufferedResamplerImpl(int, int, int) in wmadd.o
      resample(WavData const&, int) in wmget.o
  "_av_opt_set_int", referenced from:
      HLSOutputStream::open_audio(AVCodec*, AVDictionary*) in hlsoutputstream.o
  "_sf_close", referenced from:
      SFOutputStream::open(std::__1::function<SNDFILE_tag* (SF_INFO*)>, int, int, int, SFOutputStream::OutFormat) in sfoutputstream.o
      SFOutputStream::close() in sfoutputstream.o
      SFInputStream::close() in sfinputstream.o
      SFInputStream::open(std::__1::function<SNDFILE_tag* (SF_INFO*)>) in sfinputstream.o
  "_av_opt_set_sample_fmt", referenced from:
      HLSOutputStream::open_audio(AVCodec*, AVDictionary*) in hlsoutputstream.o
  "_mpg123_format", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_swr_init", referenced from:
      HLSOutputStream::open_audio(AVCodec*, AVDictionary*) in hlsoutputstream.o
  "_av_frame_get_buffer", referenced from:
      HLSOutputStream::alloc_audio_frame(AVSampleFormat, unsigned long long, int, int, Error&) in hlsoutputstream.o
  "_gcry_check_version", referenced from:
      gcrypt_init() in random.o
  "_av_interleaved_write_frame", referenced from:
      HLSOutputStream::write_frame(AVRational const*, AVStream*, AVPacket*) in hlsoutputstream.o
  "_av_packet_rescale_ts", referenced from:
      HLSOutputStream::write_frame(AVRational const*, AVStream*, AVPacket*) in hlsoutputstream.o
  "_av_frame_alloc", referenced from:
      HLSOutputStream::alloc_audio_frame(AVSampleFormat, unsigned long long, int, int, Error&) in hlsoutputstream.o
  "_avcodec_find_encoder", referenced from:
      HLSOutputStream::add_stream(AVCodec**, AVCodecID) in hlsoutputstream.o
  "Resampler::inpsize() const", referenced from:
      BufferedResamplerImpl<Resampler>::write_frames(std::__1::vector<float, std::__1::allocator<float> > const&) in wmadd.o
      void process_resampler<Resampler>(Resampler&, std::__1::vector<float, std::__1::allocator<float> > const&, std::__1::vector<float, std::__1::allocator<float> >&) in wmget.o
  "_av_dict_copy", referenced from:
      HLSOutputStream::open_audio(AVCodec*, AVDictionary*) in hlsoutputstream.o
  "_avcodec_get_name", referenced from:
      HLSOutputStream::add_stream(AVCodec**, AVCodecID) in hlsoutputstream.o
  "_avcodec_alloc_context3", referenced from:
      HLSOutputStream::add_stream(AVCodec**, AVCodecID) in hlsoutputstream.o
  "_av_get_channel_layout", referenced from:
      HLSOutputStream::add_stream(AVCodec**, AVCodecID) in hlsoutputstream.o
  "_av_log_set_level", referenced from:
      HLSOutputStream::HLSOutputStream(int, int, int) in hlsoutputstream.o
  "_mpg123_strerror", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
      MP3InputStream::read_frames(std::__1::vector<float, std::__1::allocator<float> >&, unsigned long) in mp3inputstream.o
  "_gcry_randomize", referenced from:
      Random::gen_key() in random.o
  "_gcry_cipher_close", referenced from:
      Random::~Random() in random.o
  "_gcry_strerror", referenced from:
      Random::die_on_error(char const*, unsigned int) in random.o
  "_gcry_cipher_setctr", referenced from:
      Random::seed(unsigned long long, Random::Stream) in random.o
  "Resampler::setup(unsigned int, unsigned int, unsigned int, unsigned int)", referenced from:
      create_resampler(int, int, int) in wmadd.o
      resample(WavData const&, int) in wmget.o
  "_fftwf_execute_dft_c2r", referenced from:
      fftsr_float(unsigned long, float*, float*) in fft.o
  "_gcry_strsource", referenced from:
      Random::die_on_error(char const*, unsigned int) in random.o
  "_avformat_alloc_output_context2", referenced from:
      HLSOutputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, unsigned long, double, unsigned long) in hlsoutputstream.o
  "_gcry_cipher_setkey", referenced from:
      Random::Random(unsigned long long, Random::Stream) in random.o
  "_avcodec_parameters_from_context", referenced from:
      HLSOutputStream::open_audio(AVCodec*, AVDictionary*) in hlsoutputstream.o
  "_sf_open_virtual", referenced from:
      SFOutputStream::open(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, int, int, int, SFOutputStream::OutFormat)::$_1::operator()(SF_INFO*) const in sfoutputstream.o
      SFInputStream::open(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const*)::$_1::operator()(SF_INFO*) const in sfinputstream.o
  "_av_rescale_q", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "_sf_strerror", referenced from:
      SFOutputStream::open(std::__1::function<SNDFILE_tag* (SF_INFO*)>, int, int, int, SFOutputStream::OutFormat) in sfoutputstream.o
      SFOutputStream::write_frames(std::__1::vector<float, std::__1::allocator<float> > const&) in sfoutputstream.o
      SFInputStream::open(std::__1::function<SNDFILE_tag* (SF_INFO*)>) in sfinputstream.o
      SFInputStream::read_frames(std::__1::vector<float, std::__1::allocator<float> >&, unsigned long) in sfinputstream.o
  "_mpg123_outblock", referenced from:
      MP3InputStream::read_frames(std::__1::vector<float, std::__1::allocator<float> >&, unsigned long) in mp3inputstream.o
      MP3InputStream::detect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_sf_error", referenced from:
      SFOutputStream::open(std::__1::function<SNDFILE_tag* (SF_INFO*)>, int, int, int, SFOutputStream::OutFormat) in sfoutputstream.o
      SFOutputStream::write_frames(std::__1::vector<float, std::__1::allocator<float> > const&) in sfoutputstream.o
      SFInputStream::open(std::__1::function<SNDFILE_tag* (SF_INFO*)>) in sfinputstream.o
      SFInputStream::read_frames(std::__1::vector<float, std::__1::allocator<float> >&, unsigned long) in sfinputstream.o
  "_gcry_cipher_open", referenced from:
      Random::Random(unsigned long long, Random::Stream) in random.o
  "_mpg123_rates", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "_av_init_packet", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "VResampler::inpsize() const", referenced from:
      BufferedResamplerImpl<VResampler>::write_frames(std::__1::vector<float, std::__1::allocator<float> > const&) in wmadd.o
      void process_resampler<VResampler>(VResampler&, std::__1::vector<float, std::__1::allocator<float> > const&, std::__1::vector<float, std::__1::allocator<float> >&) in wmget.o
  "_sf_open", referenced from:
      SFOutputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, int, int, SFOutputStream::OutFormat)::$_0::operator()(SF_INFO*) const in sfoutputstream.o
      SFInputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)::$_0::operator()(SF_INFO*) const in sfinputstream.o
  "_av_opt_set", referenced from:
      HLSOutputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, unsigned long, double, unsigned long) in hlsoutputstream.o
  "Resampler::process()", referenced from:
      BufferedResamplerImpl<Resampler>::write_frames(std::__1::vector<float, std::__1::allocator<float> > const&) in wmadd.o
      void process_resampler<Resampler>(Resampler&, std::__1::vector<float, std::__1::allocator<float> > const&, std::__1::vector<float, std::__1::allocator<float> >&) in wmget.o
  "VResampler::process()", referenced from:
      BufferedResamplerImpl<VResampler>::write_frames(std::__1::vector<float, std::__1::allocator<float> > const&) in wmadd.o
      void process_resampler<VResampler>(VResampler&, std::__1::vector<float, std::__1::allocator<float> > const&, std::__1::vector<float, std::__1::allocator<float> >&) in wmget.o
  "_mpg123_init", referenced from:
      mp3_init() in mp3inputstream.o
  "_av_get_channel_layout_nb_channels", referenced from:
      HLSOutputStream::add_stream(AVCodec**, AVCodecID) in hlsoutputstream.o
  "_gcry_control", referenced from:
      gcrypt_init() in random.o
  "_sf_writef_int", referenced from:
      SFOutputStream::write_frames(std::__1::vector<float, std::__1::allocator<float> > const&) in sfoutputstream.o
  "Resampler::~Resampler()", referenced from:
      BufferedResamplerImpl<Resampler>::~BufferedResamplerImpl() in wmadd.o
      resample(WavData const&, int) in wmget.o
  "_avformat_new_stream", referenced from:
      HLSOutputStream::add_stream(AVCodec**, AVCodecID) in hlsoutputstream.o
  "_av_write_trailer", referenced from:
      HLSOutputStream::close() in hlsoutputstream.o
  "VResampler::~VResampler()", referenced from:
      BufferedResamplerImpl<VResampler>::~BufferedResamplerImpl() in wmadd.o
      resample(WavData const&, int) in wmget.o
  "_av_frame_free", referenced from:
      HLSOutputStream::close_stream() in hlsoutputstream.o
  "_avcodec_receive_packet", referenced from:
      HLSOutputStream::write_audio_frame(Error&) in hlsoutputstream.o
  "Resampler::Resampler()", referenced from:
      BufferedResamplerImpl<Resampler>::BufferedResamplerImpl(int, int, int) in wmadd.o
      resample(WavData const&, int) in wmget.o
  "_mpg123_new", referenced from:
      MP3InputStream::open(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
      MP3InputStream::detect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in mp3inputstream.o
  "VResampler::setup(double, unsigned int, unsigned int)", referenced from:
      create_resampler(int, int, int) in wmadd.o
      resample(WavData const&, int) in wmget.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

由于您是使用 brew 安装的,因此您正试图 link 反对为 Mac 构建的库。您需要为 iOS 构建这些库。请注意,这通常涉及制作每个库所需的不同体系结构的胖二进制文件。您可以轻松地针对 fftw 测试它并查看 linker 错误是否消失。以下是构建或下载预构建版本的一些参考。

https://github.com/godock/fftw-build

理论上一旦你 link 对抗 iOS 版本,你应该看到像

这样的错误
_fftwf_plan_dft_r2c_1d", referenced from:
      fftar_float(unsigned long, float*, float*) in fft.o
_fftwf_free", referenced from:
      free_array_float(float*) in fft.o

消失。您还可以选择另一个库替换为 iOS 版本进行测试。例如 ffmpeg 可以在此处找到构建说明。

https://github.com/kewlbear/FFmpeg-iOS-build-script

不幸的是,您将不得不寻找如何构建它们。