Ошибка при использовании С++ в проекте Swift в Xcode: неопределенные символы для архитектуры x86_64

В сети много вопросов по этому поводу, но я не смог решить свою проблему. Я изучаю это несколько дней.

Я хочу запустить простой класс C++ в проекте Swift, для этого я следовал этому руководству: http://www.swiftprogrammer.info/swift_call_cpp.html. В основном я выполнил следующие шаги:

  1. Создайте файлы junk.cpp и junk.h
  2. Скомпилируйте с помощью g++ or/and clang++
  3. Создайте файл .a с: $ ar r libjunkcpp.a junk.o
  4. ranlib libjunkcpp.a
  5. Связан с Xcode в Build Phases -> Link Binary With Libraries -> Add

При компиляции возникают следующие ошибки:

Undefined symbols for architecture x86_64:
  "A::getInt()", referenced from:
      _getIntFromCPP in wrapper.o
  "A::A(int)", referenced from:
      _getIntFromCPP in wrapper.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

барахло.ч

class A {
    public:
    A(int);
    int getInt();

    private:
    int m_Int;
};

мусор.cpp

#include "junk.h"

A::A(int _i) : m_Int(_i) {}

int A::getInt() {
    return m_Int
}

обертка.cpp

#include "junk.h"

extern "C" int getIntFromCPP() {
    // Create an instance of A, defined in
    // the library, and call getInt() on it:
    return A(1234).getInt();
}

мост.ч

int getIntFromCPP();


person Augusto    schedule 06.12.2018    source источник
comment
Показывает ли nm libjunkcpp.a, что эти символы существуют, и скомпилирован ли он для правильной архитектуры? Кроме того, вы включили в архив и wrapper.o, и junk.o?   -  person Botje    schedule 06.12.2018
comment
Вы можете быть более ясным? Я новичок в этой работе. nm libjunkcpp.a показывает: libjunkcpp.a(junk.o):. В какой архив я должен включить эти .o файла?   -  person Augusto    schedule 06.12.2018
comment
под libjunkcpp.a(junk.o): вы должны увидеть список для A::A и A::getInt, хотя и искаженный. Для меня это показывает 0000000000000020 T __ZN1AC1Ei и __ZN1A6getIntEv.   -  person Botje    schedule 06.12.2018
comment
трудно сказать, что не так с вашей настройкой, так как выполнение ваших шагов точно создает действительную сборку, проблема, похоже, связана с libjunkcpp.a, я бы рекомендовал удалить ее и построить с нуля, также может помочь публикация команд сборки, которые не работают (Xcode: Вид -> Навигаторы -> Показать навигатор отчетов, не забываем развернуть сообщение об ошибке ;))   -  person miadz    schedule 06.12.2018
comment
Это может быть проблема с Xcode. Несколько лет назад, когда я использовал Swift с C++, моя команда столкнулась с проблемой, когда Xcode удалял символы, которые, по его мнению, не используются из статической библиотеки C++. Раньше нам приходилось использовать явный переключатель компоновщика -force_load, чтобы убедиться, что он не удаляет символы, которые, по его мнению, не используются. Если вы видите, что символы существуют в .a, но не в конечном продукте, возможно, это та же проблема. (Редактировать: Только что понял, что это старый вопрос. Я столкнулся с этой проблемой примерно в 2018 году, так что в конце концов это может быть та же проблема)   -  person Human-Compiler    schedule 10.02.2021


Ответы (1)


Это проблема, которая иногда возникает при использовании библиотек C или C++, которые подключаются через Objective-C к Swift. Проблема не в том, как построен Архив (статическая библиотека), а в чрезмерно агрессивном компоновщике, создающем приложение.

Проблема в том, что компоновщик видит символы привязки и символы C++, но никогда не видит, что он вызывается откуда-либо, потому что на самом деле он вызывается из другого языка (Swift). В конечном итоге это приводит к тому, что компоновщик агрессивно удаляет все символы, которые, по его мнению, не используются, чтобы сэкономить место, что эффективно удаляет весь код C++.

Когда это произойдет, nm сообщит о наличии в архиве правильных символов, но фактическое приложение не запустится из-за того, что символы не будут найдены.


Что касается решений, на Stack Overflow уже есть несколько вопросов/ответов, которые в той или иной степени решают эту проблему:

Трудно дать окончательный и четкий ответ без дополнительной информации о существующей настройке, например о том, где создается wrapper.cpp и как используются привязки внутри проекта Swift. Учитывая, что этот вопрос относится к 2018 году, я не подозреваю, что будет гораздо больше информации о том, какой была эта установка в то время.

Судя по описанным симптомам, это звучит точно так же, как проблема, с которой столкнулись мои коллеги при выполнении привязок C++/Swift, и в конечном итоге решение заключалось в использовании -force_load, что гарантирует полное сохранение архива в конечном приложении.

person Human-Compiler    schedule 14.02.2021