Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined symbols for architecture arm64 after linking a static library in iOS app

I am creating a sample static library to be used in my iOS app, however, when calling the static library's methods, I ran into a linker error:

Undefined symbols for architecture arm64:
"_doMath", referenced from:
  _doMathInterface in libTestMain.a(Test.o)
 (maybe you meant: _doMathInterface)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Here is the static library's structure:

I have a header file Test.h:

#import <Foundation/Foundation.h>

@interface Test : NSObject

int doMathInterface(int a, int b);

@end

and its implementation Test.m :

#import "Test.h"
#include "PaymentAPI.h"

@implementation Test

int doMathInterface(int a, int b){
    return doMath(a, b);
}

@end

and in PaymentAPI.h:

#ifndef PaymentAPI_h
#define PaymentAPI_h

int doMath(int a, int b);

#endif /* PaymentAPI_h */

Finally in PaymentAPI.cpp:

#include <stdio.h>
#include "PaymentAPI.h"

int doMath(int a, int b){
    return a + b;
}

As you can see it's a very simple static library but I couldn't figure out why this linker error is happening, I have added the static library in the "Link Binaries with Libraries" in Build Phases in the app.

Here is a screenshot of the app's files:

enter image description here

and search paths configuration in build settings is also correct, I believe:

enter image description here

Here is a screenshot of some build settings for the static library project

Build Phases: enter image description here

Architecture: enter image description here

Thanks a lot.

like image 236
zfgo Avatar asked Jul 09 '20 18:07

zfgo


1 Answers

The problem is that your doMath function gets compiled as C++ code, which means that the function name gets mangled by the C++ compiler. Your Test.m file however gets consumed by the (Objective-)C compiler and C doesn't use name mangling.

This means that the linker will end up looking for the wrong symbol. You can fix this by having the C++ compiler emit an unmangled function name. To do so, you'll have to use extern "C" in PaymenAPI.h like so:

#ifndef PaymentAPI_h
#define PaymentAPI_h

#ifdef __cplusplus
extern "C" {
#endif

int doMath(int a, int b);

#ifdef __cplusplus
}
#endif

#endif /* PaymentAPI_h */

For a complete explanation you can take a look at this SO question and the accepted answer: Combining C++ and C - how does #ifdef __cplusplus work?

like image 191
JustSid Avatar answered Sep 30 '22 07:09

JustSid