Discussion:
[Interest] Objective C Category for QCocoaApplicationDelegate undefined symbols
Croitor Alexandru
2015-07-02 11:42:56 UTC
Permalink
Hi.

I'm trying to add an Objective C category to the QCocoaApplicationDelegate
class that is defined by the Mac OS X Cocoa platform plugin, to add /
override some methods.
The QCocoaApplicationDelegate is defined in Qt's source folder
"src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h".

My code for the category is as simple as this:

// Code in osx_app_delegate.mm

#include <qglobal.h>

#include <Cocoa/Cocoa.h>


@interface QCocoaApplicationDelegate

@end


@interface QCocoaApplicationDelegate (AppDelegate)

@end



@implementation QCocoaApplicationDelegate (AppDelegate)

@end


But when I try to compile the code, I get the following error:

Undefined symbols for architecture x86_64:

"_OBJC_CLASS_$_QCocoaApplicationDelegate", referenced from:

l_OBJC_$_CATEGORY_QCocoaApplicationDelegate_$_AppDelegate in
osx_app_delegate.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see
invocation)


Doing the same (adding a category to the app delegate) on IOS works
properly.
I assume that is because the platform plugin on IOS is linked statically,
whereas on OSX it is linked dynamically.

I tried manually linking the cocoa plugin dylib file at link stage like so:

LIBS += -L/Users/X/Dev/Qt/5.4/clang_64/plugins/platforms -lqcocoa


But this doesn't help either.
Is there no way to add the category if the platform plugin is dynamically
loaded?
Is the only option to statically compile Qt, and therefore the platform
plugin as well?
Thiago Macieira
2015-07-02 16:16:17 UTC
Permalink
Post by Croitor Alexandru
Is there no way to add the category if the platform plugin is dynamically
loaded?
Is the only option to statically compile Qt, and therefore the platform
plugin as well?
You've used private API, so the correct solution is to add the proper solution
with public API to the QtGui or QtMacExtras modules.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Croitor Alexandru
2015-07-01 08:54:40 UTC
Permalink
Hi.

I'm trying to add an Objective C category to the QCocoaApplicationDelegate
class that is defined by the Mac OS X Cocoa platform plugin, to add /
override some methods.
The QCocoaApplicationDelegate is defined in Qt's source folder
"src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h".

My code for the category is as simple as this:

// Code in osx_app_delegate.mm

#include <qglobal.h>

#include <Cocoa/Cocoa.h>


@interface QCocoaApplicationDelegate

@end


@interface QCocoaApplicationDelegate (AppDelegate)

@end



@implementation QCocoaApplicationDelegate (AppDelegate)

@end


But when I try to compile the code, I get the following error:

Undefined symbols for architecture x86_64:

"_OBJC_CLASS_$_QCocoaApplicationDelegate", referenced from:

l_OBJC_$_CATEGORY_QCocoaApplicationDelegate_$_AppDelegate in
osx_app_delegate.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see
invocation)


Doing the same (adding a category to the app delegate) on IOS works
properly.
I assume that is because the platform plugin on IOS is linked statically,
whereas on OSX it is linked dynamically.

I tried manually linking the cocoa plugin dylib file at link stage like so:

LIBS += -L/Users/X/Dev/Qt/5.4/clang_64/plugins/platforms -lqcocoa


But this doesn't help either.
Is there no way to add the category if the platform plugin is dynamically
loaded?
Is the only option to statically compile Qt, and therefore the platform
plugin as well?
Till Oliver Knoll
2015-07-06 17:38:21 UTC
Permalink
Hi.
I'm trying to add an Objective C category to the QCocoaApplicationDelegate class that is defined by the Mac OS X Cocoa platform plugin, to add / override some methods.
I am not an Obj-C expert, but I'd say you need to link at Build time with the class you're trying to add a Category to. You could try to extend the (non-existent) class "MickeyMouse" with a Category and you should see similar linker errors.

But basically your own findings already confirm the above.

That said, I am not sure if Obj-C Categories actually work with code that is dynamically linked by the application itself (aka "plugin loading", dlopen() etc.). I understand that with Categories you can "add" methods even to class instances (such as instances of, say, NSString - and all subclasses thereof) that are instanciated by other libraries that don't even know about your Category. In other words, all happens at runtime. But maybe the "system linker" triggers some magic stuff, that is, "injecting" an extended message handler which first deals with your Category defined messages (aka "methods", for the Obj-
C foreigners here on the list ;)) before passing them on to the original implementation message handler? And maybe that only works with libraries that you linked (dynamically) at Build time, but not at Runtime (with dlopen)? Not sure...

But let's assume that adding a Category to plugins works and all the linker needs is a "class definition & implementation", also in the actual application ("plugin host").

You already tried to link with QCocoaApplicationDelegate, which didn't work.

But doesn't that delegate class derive from some NSApplicationWhateverDelegate? Which is probably a "Protocol" anyway, so bad luck - or can one add Categories to Protocols?

Which led me to

http://stackoverflow.com/questions/1521267/defining-categories-for-protocols-in-objective-c

and one answer talks about "ExtObjC" (an additional library, I guess). While in general you cannot extend Protocols with Categories (in vanilla ObjC), that library might help you...

Anyway, my general idea, as you have figured out, is to extend QCocoaApplicationDelegate's "base class" (or Protocol), which I guess is an NSWhatever class/protocol. Then simply link your application explicitly with -lcocoa (or the correct framework/if needed).

Maybe that gets you some ideas...

Cheers,
Oliver
Till Oliver Knoll
2015-07-06 18:51:24 UTC
Permalink
Post by Till Oliver Knoll
Hi.
I'm trying to add an Objective C category to the QCocoaApplicationDelegate class that is defined by the Mac OS X Cocoa platform plugin, to add / override some methods.
I am not an Obj-C expert, but I'd say you need to link at Build time with the class you're trying to add a Category to.
Oh one more thing ;) *Overriding* existing methods with Categories is
strongly discouraged, also (apparently) by the Apple docs!

Also refer to this question:


http://stackoverflow.com/questions/5272451/overriding-methods-using-categories-in-objective-c

(The link to the Apple Developer docs is broken however)

Cheers, Oliver

Loading...