开发者

Linker issues in C++ / ObjC

开发者 https://www.devze.com 2023-02-21 17:00 出处:网络
I\'m porting a sizeable codebase to iOS. The simplified version of my scenario is as follows: I have a C++ library, built from the command line. I can run code from it from the iOS simulator, so I

I'm porting a sizeable codebase to iOS. The simplified version of my scenario is as follows:

  • I have a C++ library, built from the command line. I can run code from it from the iOS simulator, so I believe it's correctly built.
  • I have the skeleton iOS application created by Xcode

I want to add logging to the C++ library. I have a trace() method which takes fmt, .... I compile that .cpp using -x Objective-c++, the code is as follows:

void trace (const char* sFmt, ...)
{
    va_list args;
    va_start(args, sFmt);

    NSString* sFmt2 = [ NSString stringWithUTF8String: sFmt ];
    NSLogv(sFmt2, args);

    va_end(args);
}

The library compiles just fine. However, when I try to link the app, I get a linke开发者_JAVA技巧r error:

  ".objc_class_name_NSString", referenced from: literal-pointer@__OBJC@__cls_refs@NSString in lib.a(trace.o)

This is strange because I can use NSString and NSLog from a .mm file in the project itself. The Foundation framework is linked. Moreover, just to test, instead of calling NSString from my library I added a helper foobar() to the .mm in the project, which does this

void foobar (const char* sFmt)
{
    NSLog([NSString stringWithUTF8String:sFmt]);
}

When this is called from the library function above, it works!

Everything I read about this kind of error involves a "just updated my SDK" scenario, which is not my case. I started doing iOS stuff literally two days ago, I haven't changed the default project settings, etc.

My guess is that name mangling is failing at some point, because I know NSString is indeed linked, but it seems the name refrenced by the library is different to the linked one.

Any ideas?


Your linker output indicates that your command-line-built library is lib.a, which indicates to me that it's a static library. I'd guess that, not being a dylib, it doesn't know how to use the dyloader to find missing symbols at runtime. Relatedly, I suspect that the iOS project will link in these System libraries dynamically (even though non-OS developers can't create dynamic frameworks), whereas your static C++ library will expect those symbols to be resolved at link time.

I suspect that any of these three things would resolve the issue: (in descending order of attractiveness)

  1. statically link against the right libraries when building the C++ library
  2. make the C++ library a dylib instead of a static library (so it will expect to find missing symbols at runtime using the dyloader)
  3. link your whole app statically (so the NSString class symbols are present at app link time) (This is a bad idea, if it's even possible at all, but would likely solve the problem.)

Hope this helps!


I was able to fix this by using libtool instead of ld, passing it -framework Foundation, and passing -fobjc-abi-version=2 to gcc.

0

精彩评论

暂无评论...
验证码 换一张
取 消