Search code examples
objective-cmacosxcode5

OSX command line app linker error


I have created an OSX command app in Xcode 5

Here is the main.m

#import <Foundation/Foundation.h>
#import "ConnectionListener.h"
#import "SOMatrix.h"


    int main(int argc, const char * argv[])
    {

        @autoreleasepool {


            NSLog(@"Hello, World!");

            print_m();


        }
        return 0;
    }

and here is my header file:

#ifndef __GDC1__SOMatrix__
#define __GDC1__SOMatrix__

#ifdef __cplus
#include <iostream>
#endif

int print_m();


#endif /* defined(__GDC1__SOMatrix__) */

And here is a partial listing of the SOMatrix.mm file

#include "SOMatrix.h"

#include <iostream>

using namespace std;

int print_m() {

    // logic removed to keep it short; no compile time error
    return 0;
}

When I build the project I got a linker error:

Undefined symbols for architecture x86_64:
  "_print_m", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I don't understand why the function is showhow changed to have a leading underscore in the name ('_print_m').

Why this error occurs? Do I need to add the .mm file explicitly to the project?


Solution

  • You need to change these lines:

    #ifdef __cplus
    #include <iostream>
    #endif
    

    to this in your .h file:

    #ifdef __cplusplus
    #include <iostream>
    extern "C"
    {
    #endif
    

    with a companion:

    #ifdef __cplusplus
    }
    #endif 
    

    at the end of the .h file.

    Because you are trying to access a C++ function from Objective-C, and C++ tends to do a bit of name mangling (adding the underscore, for example). Adding the "extern "C"" bit allows your Objective-C code to find your C function declarations. The answers to this related question might elaborate on things a bit better than I can.