Objective-C++ undefined symbols when linking C++ constructors

129 Views Asked by At

I'm experiencing a strange linker error when building a Mac version of a cross-platform project I'm working on. The cross-platform code is developed in C++ and I'm using Apple's AppKit in Objective-C to manage the UI frontend. As an example, I'm having a C++ class called UILabel, defined as follow:

#pragma once
#include "CoreApplication/Views/Elements/UIElement.h"
namespace CoreApplication {
class UILabel : public UIElement {
    UILabel( const UIIdentifier identifier );
    ~UILabel( void );
...

The actual code is in UILabel.cpp:

#include "CoreApplication/Views/Elements/UILabel.h"
#if( TARGET_OS == MICROSOFT_WINDOWS_OS )
...
#elif( TARGET_OS == APPLE_MAC_OS )
    #include "CoreApplication/Views/UIMacTarget.h"
#endif
namespace CoreApplication {
UILabel::UILabel( const UIIdentifier identifier )
    : UIElement( identifier )
    , _label( NULL )
    , _textAlignment( TextAlignmentType::Void )
    , _textWeight( TextWeightType::Void )
{
    M_LOG_CONSTRUCTOR
    _CreateHostUIElement();
    _ConnectHostUIElement();
    // Default text attributes:
    SetTextAlignment( TextAlignmentType::Left );
    SetTextWeight( TextWeightType::Normal );
}
...

When instantiating a new UILabel object in a Objective-C++ file (.mm), I'm having the following message from clang:

ld: Undefined symbols: CoreApplication::UILabel::UILabel(unsigned int), referenced from: -[AppDelegate applicationDidFinishLaunching:] in AppDelegate.o

The Objective-C code in the AppDelegate.mm file is:

#import "CoreApplication/Views/Elements/UILabel.h"
using namespace CoreApplication;
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    UILabel label( kNullUIIdentifier );
    Pointer hLabel = CreateMacUILabel( label );
    label.SetLabel( CSTR("Hello Macintosh") );
...

The interesting part is that I'm also using a "neutral" String class to work with Windows and MacOS defined as below:

#include "CoreServices/Streams/MutableData.h"
namespace CoreServices {
class String : public MutableData {
public:
    String( void );
    String( const String & source );
    String( const char * source );
...

and the following code in the same AppDelegate method is being linked without issue:

using namespace CoreServices;
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    String coreServicesInput( "Hello Macintosh" );
...

I checked the build phase order in Xcode but everything seems to be OK: what am I doing wrong here?

Needless to say that this code is working fine on Windows with Visual Studio and C++/winRT UWP.

PS: All code is being compiled/linked in the same project: no library here.

1

There are 1 best solutions below

1
alphafox75 On

Thank you all for your answers and comments. The issue originated from a wrong uint32 type definition in the Mac context. Instead of unsigned int, it was unsigned long in some conditional #if/#endif header section.

I can use #include <stdint> to ensure the common fixed width integer types are correctly defined.

However, I'm now using the pstdint header from Paul Hsieh that you can find at http://www.azillionmonkeys.com/qed/pstdint.h

I prefer this version as it comes with some interesting macros for correct printf() usage on those types (my code includes many, many log/debug snippets!).