OSX command line app linker error - objective-c

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?

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.

Related

Why calling objc function from objc++ could result in build failure?

Given this MVP code:
objc_funcs.h
#import <Foundation/Foundation.h>
NSString* doFoo(void);
objc_funcs.m
#import <Foundation/Foundation.h>
NSString* doFoo()
{
return #"fffuuu";
}
main.mm
#import "objc_funcs.h"
int main(int argc, char * argv[]) {
doFoo();
return 0;
}
If I leave it this way, the build will result in
Undefined symbols for architecture x86_64:
"doFoo()", 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)
Though if I rename main.mm -> main.m, the build will go just fine.
WAIDW? 😖
The problem relates to C vs C++ linkage.
The normal way this is handled in C headers is testing for the __cplusplus preprocessor macro and inserting an extern "C" if needed. CoreFoundation provides the CF_EXTERN_C_BEGIN and CF_EXTERN_C_END macros that handle this:
#if !defined(CF_EXTERN_C_BEGIN)
#if defined(__cplusplus)
#define CF_EXTERN_C_BEGIN extern "C" {
#define CF_EXTERN_C_END }
#else
#define CF_EXTERN_C_BEGIN
#define CF_EXTERN_C_END
#endif
#endif
Using these your objc_funcs.h becomes:
#import <Foundation/Foundation.h>
CF_EXTERN_C_BEGIN
NSString* doFoo(void);
CF_EXTERN_C_END
if you don't want to use them you could use
#import <Foundation/Foundation.h>
#ifdef __cplusplus
extern "C"
#endif
NSString* doFoo(void);
You have to make it valid for C++ compiler by either converting objc_funcs to .mm file or wrapping the import in main.mm with extern "C" {}:
extern "C" {
#import "objc_funcs.h"
}
You could read more about it here

ObjectiveC target can't find module, Swift working fine

I'm building a framework that needs to work with Swift and Objective-C. It is built with Swift.
It works fine in a Swift app. #import MyFrameworkName works just as expected. But I can't seem to make it work in an Objective-C app.
#import <MyFrameworkName/MyFrameworkName-Swift.h>
This is the build log:
<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/MyFrameworkName.h"
^
/Users/user/Projects/MyFrameworkName/Sources/MyFrameworkName.h:20:9: error: module 'CommonCryptoBridge' not found
#import CommonCryptoBridge;
^
<unknown>:0: error: could not build Objective-C module 'MyFrameworkName'
This is my framework header:
#import <UIKit/UIKit.h>
FOUNDATION_EXPORT double MyFrameworkNameVersionNumber;
FOUNDATION_EXPORT const unsigned char MyFrameworkNameVersionString[];
#import CommonCryptoBridge;
The CommonCryptoBridge is a module to enable CommonCrypto in Swift, defined by CommonCryptoBridge.h and CommonCryptoBridge.modulemap:
CommonCryptoBridge.h
#ifndef __COMMONCRYPTO_BRIDGE__
#include <CommonCrypto/CommonCrypto.h>
#define __COMMONCRYPTO_BRIDGE__
#endif /* __COMMONCRYPTO_BRIDGE__ */
CommonCryptoBridge.modulemap
module CommonCryptoBridge [system] {
header "CommonCryptoBridge.h"
export *
}

QT run objective-c code

I'm trying to run native object-c code on my Mac application.
My code looks like:
MainWindow.h:
#ifdef Q_OS_MAC
#include <Carbon/Carbon.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>
#endif
MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
#ifdef Q_OS_MAC
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
selector: #selector(receiveSleepNote:)
name: NSWorkspaceWillSleepNotification object: NULL];
#endif
}
#ifdef Q_OS_MAC
- (void) receiveSleepNote: (NSNotification*) note
{
NSLog(#"receiveSleepNote: %#", [note name]);
}
#endif
But am getting errors that seems that QT does not understand the code structure:
application.cpp: error: expected external declaration
- (void) receiveSleepNote: (NSNotification*) note ^
In order to compile objective-c with C++, you need to have the objective-c code in a .m or .mm file.
The accompanying header can then contain functions that can be called from C++ and the body of those functions can contain objective-c code.
So let's say, for example, we wanted to call a function to pop up an OSX notification. Start with the header: -
#ifndef __MyNotification_h_
#define __MyNotification_h_
#include <QString>
class MyNotification
{
public:
static void Display(const QString& title, const QString& text);
};
#endif
As you can see, this is a regular function in a header that can be called from C++. Here's the implementation:-
#include "mynotification.h"
#import <Foundation/NSUserNotification.h>
#import <Foundation/NSString.h>
void MyNotification::Display(const QString& title, const QString& text)
{
NSString* titleStr = [[NSString alloc] initWithUTF8String:title.toUtf8().data()];
NSString* textStr = [[NSString alloc] initWithUTF8String:text.toUtf8().data()];
NSUserNotification* userNotification = [[[NSUserNotification alloc] init] autorelease];
userNotification.title = titleStr;
userNotification.informativeText = textStr;
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:userNotification];
}
The implementation contains objective-c and due to its .mm file extension, the compiler will handle this correctly.
Note that in the example you provide in the question, you need to think about what the code is doing; especially when using 'self', as I expect that would need to refer to an Objective-C class, not a C++ class.

Undefined symbols for architecture x86_64 in hello world

Today I'm learning Objective-C without Xcode following this Guide
Here's the hello world:
makclass.m
#import "makclass.h"
#import <stdio.h>
#implementation MakClass
-(void) age {
printf("Age is %d", age);
}
-(void) setAge: (int) a {
age = a;
}
+(void) say {
printf("Haha");
}
#end
makclass.h
#import <Foundation/NSObject.h>
#interface MakClass: NSObject {
int age;
}
-(void) age;
-(void) setAge: (int) a;
+(void) say;
#end
helloworld.m
#import <stdio.h>
#import "makclass.h"
int main(void) {
printf("Hello World");
MakClass *makclass = [[MakClass alloc] init];
[makclass setAge: 1];
[makclass age];
[MakClass say];
[makclass release];
return 0;
}
And clang helloworld.m give me the following errors:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_MakClass", referenced from:
objc-class-ref in helloworld-XEijke.o
"_objc_msgSend", referenced from:
_main in helloworld-XEijke.o
"_objc_msgSend_fixup", referenced from:
l_objc_msgSend_fixup_alloc in helloworld-XEijke.o
l_objc_msgSend_fixup_release in helloworld-XEijke.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
You need to make sure you pass in the framework and all the files as well:
clang -framework Foundation -o helloworld helloworld.m makclass.m
Welcome to Objective-C!
When you compile, you need to specify all of the implementation files that helloworld.m requires. Just because the header files are included does not mean that the implementation files will be included as well.
Additionally, since this is Objective-C, make sure you also include the -lObjC flag to include the Objective-C libraries.
So, the command that you should run will look like clang -lObjC helloworld.m makclass.m.
clang will then spit out a program called a.out, which you can run. If you want to change the name from a.out to, say, helloworld, you can specify that with the -o flag. For example:
clang -lObjc -o helloworld helloworld.m makclass.m
Hope this helps!

Calling Functions using Objective-C and C++

Alright, I'm trying to call a function in xcode but apparently it isn't working. I made an objective-c class, and typed in the following code into the implementation file:
#import "Person.h"
#implementation Person
void printthis()
{
NSLog(#"Hi, I have been printed");
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
printthis();
}
return 0;
}
#end
Apparently, it returns the following error in xcode:
ld: 1 duplicate symbol for architecture x86_64
clang: error:
linker command failed with exit code 1 (use -v to see invocation)
Did you already have a main function somewhere else (probably main.m ?). If so the linker got confused -- you are not supposed to have duplicates of main function