Проблема компоновщика с использованием Objective-C ++ с Objective-C - PullRequest
0 голосов
/ 12 ноября 2018

В настоящее время у меня есть проект iOS, который использует Objective-C. По соображениям производительности я реализовал код Objective-C ++, который выглядит следующим образом:

base11.mm

#include <string>
#include "base11.h"

static const std::string characters = "0123456789_";

const char* to_base11(long n) {
    // some c++ code here
}

long from_base11(const char* input) {
    // some c++ code here
}

base11.h

#ifndef base11_h
#define base11_h

#include <stdio.h>

const char* to_base11(long n);
long from_base11(const char* input);

#endif /* base11_h */

Конечно, я использовал расширение .mm для класса, и я использую только простые параметры функции C и возвращаемые типы.

Затем у меня есть класс Objective-C, который оборачивает эти функции C ++ в следующие методы:

Util.m

#include "base11.h"

+(NSString*) convertBase10ToBase11:(long) base10 {
    const char* base11 = to_base11(base10);
    return [NSString stringWithUTF8String:base11];
}

+(NSNumber*) convertBase11ToBase10:(NSString*) base11 {
    const char* input = [base11 UTF8String];
    return @(from_base11(input));
}

И Util.h :

@interface Util : NSObject
    +(NSString*) convertBase10ToBase11:(long) base10;
    +(NSNumber*) convertBase11ToBase10:(NSString*) base11;
@end

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

Undefined symbols for architecture x86_64:
  "_from_base11", referenced from:
      +[Util convertBase11ToBase10:] in Util.o
  "_to_base11", referenced from:
      +[Util convertBase10ToBase11:] in Util.o
ld: symbol(s) not found for architecture x86_64

Однако это очень странно. Я решил НЕ использовать расширение .mm для класса Util.m, поскольку там я не использую код C ++. Также обратите внимание, что заголовочный файл base11.h также не использует код на C ++. Итак, почему я получаю эту ошибку? Согласно этому посту мой подход должен быть правильным:

Как вызвать метод для файла .mm из целевого класса c

1 Ответ

0 голосов
/ 12 ноября 2018

Это проблема в имени символа функции.C ++ допускает функции с одинаковыми именами и разными прототипами.Поэтому, когда функции, скомпилированные с C ++ / Objective-C ++, получают имя символа, которое описывает его прототип и делает его уникальным.

Так что вам нужно заставить компилятор использовать имя символа C.Вы можете добиться этого, добавив extern "C" перед прототипом функции.Но это не очень удобно, если вы используете этот заголовок в исходных файлах C и C ++, потому что C не знает, что это такое extern "C".

К счастью CoreFoundation уже решили эту проблему.Вы можете посмотреть, как они объявили свои CFString.h, CFArray.h.

Так что вам просто нужно использовать макрос CoreFoundation: CF_EXTERN_C_BEGIN и CF_EXTERN_C_END.

#ifndef base11_h
#define base11_h

#include <stdio.h>
#include <CoreFoundation/CFBase.h>

CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN

const char* to_base11(long n);
long from_base11(const char* input);

CF_EXTERN_C_END
CF_IMPLICIT_BRIDGING_DISABLED

#endif /* base11_h */
...