2

There are a lot of questions about this on the web but I couldn't solve my problem. I've been studying this for a few days.

I want run a simple C++ class on Swift project, to this I followed this tutorial: http://www.swiftprogrammer.info/swift_call_cpp.html. Basically I've followed the steps:

  1. Create junk.cpp and junk.h files
  2. Compile using g++ or/and clang++
  3. Create .a file with: $ ar r libjunkcpp.a junk.o
  4. ranlib libjunkcpp.a
  5. Linked to Xcode in Build Phases -> Link Binary With Libraries -> Add

When I compiles, the follow errors occurs:

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)

junk.h

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

    private:
    int m_Int;
};

junk.cpp

#include "junk.h"

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

int A::getInt() {
    return m_Int
}

wrapper.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();
}

bridge.h

int getIntFromCPP();

Augusto
  • 3,825
  • 9
  • 45
  • 93
  • Does `nm libjunkcpp.a` show that those symbols exist and did you compile it for the correct architecture? Also, did you include both `wrapper.o` and `junk.o` in the archive? – Botje Dec 06 '18 at 12:57
  • Do you can be more clear? I'm newest at this work. `nm libjunkcpp.a` shows: `libjunkcpp.a(junk.o):`. Which archive I must include these `.o` files ? – Augusto Dec 06 '18 at 13:02
  • under `libjunkcpp.a(junk.o)`: you should see a listing for `A::A` and `A::getInt`, albeit mangled. For me it shows "0000000000000020 T __ZN1AC1Ei" and "__ZN1A6getIntEv". – Botje Dec 06 '18 at 14:51
  • it's hard to tell what's wrong with your setup as following your steps exactly produces a valid build, the problem seems to be with `libjunkcpp.a`, I would recommend to remove it and build from scratch, also posting the build commands that fail may help (Xcode: View -> Navigators -> Show Report Navigator, do not forget to expand the error message ;) ) – miadz Dec 06 '18 at 16:48
  • This could be an Xcode problem. Years ago when I was using Swift with C++, my team ran into an issue where Xcode would strip symbols that it thinks aren't used from the C++ static library. We used to have to use an explicit linker switch `-force_load` to ensure that it didn't "strip" symbols that it thought weren't being used. If you see that the symbols exist in the `.a`, but not in the final product, then this might be the same issue. (**Edit:** Just realized this is an old question. I hit this issue around 2018, so it might be the same problem after all) – Human-Compiler Feb 10 '21 at 04:43

1 Answers1

0

This is an issue that sometimes occurs when using C or C++ libraries that get bridged through Objective-C into Swift. The issue isn't with how the Archive (static library) is built -- rather, it's a problem with an overly-aggressive linker creating the application.

The problem is that the linker sees the binding symbols and the C++ symbols, but never sees it being called from anywhere because it is actually invoked from a different language (Swift). This ultimately results in the linker aggressively stripping all symbols that it doesn't believe are being used in an effort to save space, which effectively removes all of the C++ code.

When this happens, nm will report the correct symbols as existing in the archive, but the actual application will fail to execute due to the symbols not being found.


As for solutions, there are actually several questions/answers already on Stack Overflow that address this issue in varying degrees:

It is difficult to provide a definitive and clear answer without more information on the existing setup, such as where wrapper.cpp is built, and how the bindings get used from within the Swift project. Given that this question is from 2018, I don't suspect there will be much more information on what this setup was at the time.

From the described symptoms, this sounds exactly like the issue my colleagues faced when doing C++/Swift bindings -- and the solution was ultimately to use -force_load which ensures that the archive is preserved in totality into the final application.

Human-Compiler
  • 11,022
  • 1
  • 32
  • 59