Ошибка компоновщика при использовании extern "C" в коде Objective-C - PullRequest
4 голосов
/ 11 сентября 2011

Я пытаюсь создать некоторые служебные функции, которые можно вызывать из кода Objective-C и C ++ в приложении для iPhone. У меня есть сторонние классы C ++, которые нельзя скомпилировать как ObjectiveC ++ (.mm). У меня есть заголовочный файл, объявляющий мои функции, а затем файл .c, определяющий их. Я утроил проверку на наличие орфографических ошибок, но по какой-то причине мой компоновщик НЕ может найти определение какой-либо функции.

Вот заголовок для вспомогательных функций C:

#ifndef FILE_LOADER_H
#define FILE_LOADER_H

#if __cplusplus
extern "C" {
#endif

void * loadDataFromFile(const char * szFilename, bool bDocument);
void * loadImageFromFile(const char * szFilename, bool bDocument);
void loadMeshFromFile(const char *szFilename, void* pMesh);

#if __cplusplus
}   // Extern C
#endif

#endif

А вот и файл .c:

#include "FileLoader.h"
#include <objc/objc.h>
#include <objc/message.h>
#include <Foundation/Foundation.h>


void * loadDataFromFile(const char * szFilename, bool bDocument)
{
    Class loaderClass = NSClassFromString(@"Loader");
    void * pReturnVal = objc_msgSend(loaderClass,   NSSelectorFromString(@"loadDataFromFile:document"), szFilename, bDocument);
    return pReturnVal;
    //return [Loader loadDataFromFile:szFilename document:bDocument];
}
void * loadImageFromFile(const char * szFilename, bool bDocument)
{
    Class loaderClass = NSClassFromString(@"Loader");
    void * pReturnVal = objc_msgSend(loaderClass, NSSelectorFromString(@"loadImageFromFile:document"), szFilename, bDocument);
    return pReturnVal;
    //return (void*)[Loader loadImageFromFile:szFilename document:bDocument];
}
void loadMeshFromFile(const char *szFilename, void* pMesh)
{
    Class loaderClass = NSClassFromString(@"Loader");
    objc_msgSend(loaderClass, NSSelectorFromString(@"loadMeshFromFile:mesh"), szFilename, pMesh);
    //[Loader loadMeshFromFile:szFilename mesh:pMesh];
}

Я попытался скомпилировать с и без внешнего "C", но с тем же результатом ошибки компоновщика.

Может кто-нибудь пролить свет на то, что я делаю неправильно?

Ошибка компоновщика:

Undefined symbols for architecture i386:
"loadMeshFromFile(char const*, void*)", referenced from:

ОБНОВЛЕНИЕ: Мне кажется, я решил эту проблему, скомпилировав исходный файл как цель C, хотя на самом деле не было кода ObjectiveC, может кто-нибудь сказать мне, почему указанный выше исходный файл не скомпилируется как код C?

Ответы [ 2 ]

8 голосов
/ 11 сентября 2011

используйте следующую конструкцию для указания связи c для переводов c и c ++:

#if !defined(__cplusplus)
#define MONExternC extern
#else
#define MONExternC extern "C"
#endif
// declare loadMeshFromFile
MONExternC void loadMeshFromFile(char const*, void*);

это объявление будет совместимо с c, objc, c ++, objc ++.

0 голосов
/ 11 сентября 2011

Дважды проверьте вашу архитектуру - проблема с компоновщиком в том, что он не компилирует ваш файл .c, а не в том, что он не может определить связь. Итак, вот что происходит ...

Компилятор проходит, не может найти способ правильно скомпилировать файл .c Линкер видит внешнюю связь C, говорит: «Хорошо, давайте посмотрим, сможем ли мы ее найти», не может найти ее, потому что .c файл не скомпилирован в объектный код, о, дерьмо, отмена.

Вам нужно проверить фазу сборки - перейдите к своим целям, выберите любую цель, активную, посмотрите, что происходит на этапе компиляции - я думаю, что какая-то цель, к которой вы стремитесь (выпуск или отладка), получена этот файл добавлен как цель i386 вместо arm, поэтому он запутался и не может найти правило для его компиляции (вы не ориентируетесь на i386, поэтому у него нет правил для его компиляции).

Если ничего не помогло, попробуйте сделать новую цель для оружия и посмотрите, сможете ли вы использовать ее таким образом, или переключите цели с выпуска на отладку и т. Д.

Если вы покажете мне снимок цели, для которой вы компилируете, я, вероятно, смогу быть намного более полезным :). Удачи!

...