GLB - iOS Compilation error

Previous topic - Next topic

aroldo

I am trying some code from DaCarSoft from the spanish forum http://www.glbasic.com/forum/index.php?topic=6463.msg79425#msg79425


I Created a GLB project and included iOSKeyBoadTest.gbas and the iOSKeyBoadTest.mm

when I compile I get the following errors from the linker:

Code: GLBasic [Select]
linking:
gpc_temp0.o:gpc_temp0.cpp:(.text+0x1f6): undefined reference to `_iOSMessageBox'
gpc_temp0.o:gpc_temp0.cpp:(.text+0x59a): undefined reference to `_GetiOSMessageBoxValues'
gpc_temp0.o:gpc_temp0.cpp:(.text+0x6ed): undefined reference to `_iOSMessageBox'
gpc_temp0.o:gpc_temp0.cpp:(.text+0x8ef): undefined reference to `_GetiOSMessageBoxValues'
*** FATAL ERROR - Please post this output in the forum

The  iOSKeyBoadTest.gbas includes this code:

Code (glbasic) Select

IMPORT "C" void iOSMessageBox(const char*,const char*, const char*, const char*)
IMPORT "C" const char* GetiOSMessageBoxValues()

GLOBAL MENSAJE$

// El nuevo símbolo de separación para los parámetros a pasar a la función es la "tubería", antes era $, en mi código anterior...
iOSMessageBox("Título","Mensaje" + CHR$(0xD) + CHR$(0xD) + CHR$(0xD) + CHR$(0xD), "Esto es una prueba  ü Ñ |:P", "Aceptar|Cancelar")

LOCAL InstanteComienzo% = GETTIMERALL()

MENSAJE$ = ""
WHILE MENSAJE$ = ""
        SLEEP 500
        WHILE ABS(GETTIMERALL() - InstanteComienzo%) < 500
                HIBERNATE
        WEND

        MENSAJE$ = GetiOSMessageBoxValues()
WEND

PRINT MENSAJE$, 100, 100

SHOWSCREEN
HIBERNATE
MOUSEWAIT



iOSMessageBox("Título","Mensaje" + CHR$(0xD) + CHR$(0xD), "Esto es otra prueba", "Aceptar|Cancelar")

InstanteComienzo% = GETTIMERALL()

MENSAJE$ = ""
WHILE MENSAJE$ = ""
        SLEEP 500
        WHILE ABS(GETTIMERALL() - InstanteComienzo%) < 500
                HIBERNATE
        WEND

        MENSAJE$ = GetiOSMessageBoxValues()
WEND

PRINT MENSAJE$, 100, 100

SHOWSCREEN
HIBERNATE
MOUSEWAIT



and the iOSKeyBoadTest.mm this:


Code (glbasic) Select
#if defined (TARGET_OS_IPHONE)



// UIALERT

//#import <UIKit/UIAlert.h>    // No es necesario duplicar la importación hecha con anterioridad

@interface GLBasicMessageBoxer: NSObject <UIAlertViewDelegate>
{
    // Declaración de los punteros para los elementos comunes
    UITextField* txtObject;
    NSMutableArray* resObjects;
    NSString* resValues;
    NSString* pTitle,* pMessage,* pLabels,* pButtons;
}
@end

@implementation GLBasicMessageBoxer

// Llamada necesaria para llamar al código que muestra el Alert en el proceso principal
- (void)showAlertCaller:(NSString*)cTitle andMessage:(NSString*)cMessage andLabels:(NSString*)cLabels andButtons:(NSString*)cButtons
{
    // Introducción de los valores pasados como parámetro punteros accesibles por "showAlert"
    pTitle = [[NSString alloc] initWithString:cTitle];
    pMessage = [[NSString alloc] initWithString:cMessage];
    pLabels = [[NSString alloc] initWithString:cLabels];
    pButtons = [[NSString alloc] initWithString:cButtons];
    // Llamada a "showAlert" enviándola al proceso principal
    [self performSelectorOnMainThread:@selector(showAlert) withObject:nil waitUntilDone:NO];
}
   
- (void)showAlert
{
        // Creación de la vista para el Alert
    UIAlertView* alert = [[UIAlertView alloc] init];
        alert.title = pTitle;
        alert.message = pMessage;
        alert.delegate = self;
    // Anulación de la asignación de la función de cancelar al botón con índice 0
    alert.cancelButtonIndex = -1;
        // Creación de la matriz de botones introduciendo valores según los parámetros pasados separados por "|"
        NSArray* aButtons = [pButtons componentsSeparatedByString:@"|"];
    // Creación de cada botón a partir de cada valor de la matriz
        for (NSString* iObject in aButtons){
                [alert addButtonWithTitle:iObject];
        }
        // Creación de la matriz de controles de texto introduciendo valores según los parámetros pasados separados por "|"
        if (pLabels != @"") {
                double iPos = 70.0;
                NSArray* aLabels = [pLabels componentsSeparatedByString:@"|"];
        resObjects = [[NSMutableArray alloc] init];
        // Creación de cada control de texto con las propiedades adecuadas asegurando que no devuelve un valor "(null)" mediante .text = @""
                for (NSString* iObject in aLabels){
                        txtObject = [[UITextField alloc] init];
                        txtObject.frame = CGRectMake(12.0, iPos, 260.0, 25.0);
            txtObject.text = @"";
                        txtObject.placeholder = iObject;
                        txtObject.backgroundColor = [UIColor whiteColor];
                        txtObject.clearButtonMode = UITextFieldViewModeWhileEditing;
                        txtObject.keyboardType = UIKeyboardTypeAlphabet;
                        txtObject.keyboardAppearance = UIKeyboardAppearanceAlert;
                        txtObject.autocapitalizationType = UITextAutocapitalizationTypeNone;
                        txtObject.autocorrectionType = UITextAutocorrectionTypeNo;
                        txtObject.borderStyle = UITextBorderStyleLine;
            // Colocación del foco si es el primer control creado para introducción de texto
                        if ([aLabels indexOfObject:iObject] == 0) {
                                [txtObject becomeFirstResponder];
                // El teclado aparece automáticamente al colocar el foco en un control de texto
                        }
            // Aumentar el valor de la variable que controla la coordenada de posición del "top" de cada control de texto
                        iPos = iPos + 30.0;
                        // Asociación de cada control a la matriz mutable
            [resObjects addObject:txtObject];
            // XCode soporta añadir controles de texto directamente a un Alert pero Apple no permite su uso directo al no estar documentado
            // Para poder imitar el comportamiento pueden agregarse "subvistas" al Alert e introducir los controles necesarios en ellas
                        [alert addSubview:txtObject];
            [txtObject release];
            txtObject = nil;
                       
                }
               
        }
       
        [alert show];
        [alert release];
}

// Recogida del botón pulsado en la memoria mediante la propiedad "delegate" (= self) asignada en "showAlert"
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
        resValues = [[NSString alloc] initWithFormat:@"%d", buttonIndex];
}

// Código que obtiene y trata los valores para construir el resultado mediante valores separados por "|"
- (void)getValues
{
    // Agregado a la cadena del botón pulsado de los valores de cada control de texto en el Alert
    for (UITextField* iObject in resObjects){
        // Insertar el texto recogido del control en un NSMutableString
        NSMutableString* tmpObjectValue = [[NSMutableString alloc] initWithString:iObject.text];
        // Reemplazar el caracter usado en el código como separador de valores si el usuario lo ha introducido en los controles
        [tmpObjectValue replaceOccurrencesOfString:@"|" withString:@"!" options:0 range:NSMakeRange(0, [tmpObjectValue length])];
        // Agregar el valor obtenido al contenido anterior de la memoria
        resValues = [resValues stringByAppendingFormat:@"|%@", tmpObjectValue];
        // Liberar la memoria
        [tmpObjectValue release];
        tmpObjectValue = nil;
    }
    // Creación de otro puntero "NSData" temporal para albergar los valores obtenidos transformados para evitar errores por "encodings"
    NSData* tmpValuesEncoded = [[NSData alloc] init];
    // Conversión de la cadena obtenida a un "encoding" Windows Latin obviando los caracteres no reconocidos mediante "allowLossyConversion"
    tmpValuesEncoded = [resValues dataUsingEncoding:NSWindowsCP1252StringEncoding allowLossyConversion:YES];
    // Reintroducción de la cadena final convertida al "encoding" adecuado para que pueda devolverse desde "getValuesCaller"
    resValues = [[NSString alloc] initWithData:tmpValuesEncoded encoding:NSWindowsCP1252StringEncoding];
    // Liberar la memoria
    tmpValuesEncoded = nil;
}

// Obtención de los valores del botón pulsado y texto introducido en los controles recuperando los valores desde el proceso principal
- (const char*)getValuesCaller
{
    // Comprobación de si se ha pulsado un botón del Alert
    if (resValues != nil){
        // Llamada a "getValues" en el proceso principal
        [self performSelectorOnMainThread:@selector(getValues) withObject:nil waitUntilDone:YES];
        // Devolvemos el valor de la cadena preparada desde "getValues"
        return [resValues cStringUsingEncoding:NSWindowsCP1252StringEncoding];
        // Liberar la memoria
        [resObjects release];
        resObjects = nil;
        [resValues release];
        resValues = nil;
        [pTitle release];
        pTitle = nil;
        [pMessage release];
        pMessage = nil;
        [pLabels release];
        pLabels = nil;
        [pButtons release];
        pButtons = nil;
        [self release];
        [super dealloc];
    }
    else
    {
        // Si no se ha pulsado ningún botón se devuelve una cadena vacía
        return "";
    }
}

@end

// Creación del puntero para las funciones contenidas en "GLBasicMessageBoxer" a usar cada vez que se requiera un Alert
GLBasicMessageBoxer* newAlert;



// Creación de función "externalizada" a usar desde GLBasic (los parámetros "labels" y "buttons" pueden contener varios valores separados con "$")
extern "C" void iOSMessageBox(const char* cTitle, const char* cMessage, const char* cLabels, const char* cButtons)
{
        newAlert = [[GLBasicMessageBoxer alloc] init];
    // Conversión de tipos "C" a "NSString" al recuperar los parámetros enviados desde GLBasic y lanzado del Alert
        [newAlert showAlertCaller:[NSString stringWithCString:cTitle encoding:NSASCIIStringEncoding] andMessage:[NSString stringWithCString:cMessage encoding:NSASCIIStringEncoding] andLabels:[NSString stringWithCString:cLabels encoding:NSASCIIStringEncoding] andButtons:[NSString stringWithCString:cButtons encoding:NSASCIIStringEncoding]];
}

// Creación de la función "externalizada" a usar desde GLBasic (los parámetros devueltos son valores separados con "$")
extern "C" const char* GetiOSMessageBoxValues()
{
    // Se recuperan en primer lugar el índice de botón pulsado y a continuación los textos introducidos en los controles generados
        return [newAlert getValuesCaller];
}

// FIN UIALERT



#endif

[a http://apd-games.com/][img http://apd-games.com/images/APDGames135.png][/a]
MacBook Pro OS X El Capitan
XCode Version 7
iPhone 6 running  iOS 9
iPad Mini running  iOS 7.1
Galaxy S5
Dell Latitude Windows 8 Enterprise
Palm Pre, Palm Pre2

MrTAToad

Are you adding the nm file to the XCode project ?

aroldo

Yes I it is in the XCode project directory, but the compilation error is happening in GLB!
[a http://apd-games.com/][img http://apd-games.com/images/APDGames135.png][/a]
MacBook Pro OS X El Capitan
XCode Version 7
iPhone 6 running  iOS 9
iPad Mini running  iOS 7.1
Galaxy S5
Dell Latitude Windows 8 Enterprise
Palm Pre, Palm Pre2

marovada

Have you selected multiplatform build for iphone? 

You'll get those linker errors if you build for windows.  I think what happens is that if you build for iphone the linker doesn't try to resolve the external functions.  The library the compiler builds will be linked in xcode to the mm file.  But if you don't build for iphone then the linker tries to resolve the external functions and won't find them because it doesn't link to the mm file.

Just my 2 cents.

aroldo

Yes I did.

Like I said the error I reported is from GLBasic and I tried in V10.xxx and V11.xxx same result.

If I ignore the GLBasic error and execute my code in Xcode Liinker complains about undefined symbols as you can see below.

Code (glbasic) Select
Undefined symbols for architecture armv7:
  "_iOSMessageBox", referenced from:
      __GLBASIC__::__MainGameSub_() in libPROGRAM.a(gpc_temp0.o)
  "_GetiOSMessageBoxValues", referenced from:
      __GLBASIC__::__MainGameSub_() in libPROGRAM.a(gpc_temp0.o)
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

[a http://apd-games.com/][img http://apd-games.com/images/APDGames135.png][/a]
MacBook Pro OS X El Capitan
XCode Version 7
iPhone 6 running  iOS 9
iPad Mini running  iOS 7.1
Galaxy S5
Dell Latitude Windows 8 Enterprise
Palm Pre, Palm Pre2

marovada

#5
I'm using v 10.283.

I started a new project.  Copied and pasted the contents of your gbas file.  I didn't do anything with the code in your mm file - left it out completely.

I chose 'build' (f8) from the menu and got the following linker errors:

Code (glbasic) Select
gpc_temp0.o:gpc_temp0.cpp:(.text+0x1da): undefined reference to `_iOSMessageBox'
gpc_temp0.o:gpc_temp0.cpp:(.text+0x3e9): undefined reference to `_GetiOSMessageBoxValues'
gpc_temp0.o:gpc_temp0.cpp:(.text+0x6ac): undefined reference to `_iOSMessageBox'
gpc_temp0.o:gpc_temp0.cpp:(.text+0x8b0): undefined reference to `_GetiOSMessageBoxValues'


I then chose 'build multiplatform' (shift f8), chose iPhone pressed ok and got no link errors.  That's why I thought you may not have been building for iPhone.

I think the error means that your object file (gpc_temp0.o) makes reference to functions that the linker can't find.

Edit: I'm just not sure why there is an attempt to link your object files when building for iPhone because they should just be aggregated into a library (libPROGRAM.a) for xcode to link against.

Can you step out what you're doing?

aroldo

marovada,

Thanks again, I agree with your comment , the references should be in the libPROGRAM.a, the GLBasic compeller/Linker should be doing that.
Something is missing in the gbas file.

I will keep researching the forum and the Xcode tutorials.

What do you mean by: Can you step out what you're doing?

If I understood correctly, I am trying to open the iOS native keyboard, and receive key strokes in the GBL program.

My goal is to learn how to pass and receive data from iOS into GLB and then implement iAds
[a http://apd-games.com/][img http://apd-games.com/images/APDGames135.png][/a]
MacBook Pro OS X El Capitan
XCode Version 7
iPhone 6 running  iOS 9
iPad Mini running  iOS 7.1
Galaxy S5
Dell Latitude Windows 8 Enterprise
Palm Pre, Palm Pre2

marovada

#7
Hi aroldo,

I meant to ask how you set up the project and then compiled it in GLBasic ie the steps you took to create a new project, add the files, choose compile option etc. 

I'm asking this because I got your code to work by copying the code from your gbas file (in your first post) into a new project.  It works perfectly for me when I build for iPhone so there is nothing missing in the gbas file. 

It's odd that it didn't work for you because I'm using the same code.  I only got the errors you've been getting when I build for windows, not for iPhone.

Edit: when you build for windows the linker tries to resolve the missing functions because it's creating an executable file.  When you build for iPhone, you're just building a library of object files so there is no need to resolve the missing functions.  They will get picked up by xcode when you build the mm file and link against the library to get the iphone executable ('app').  So it just sounds to me like there's some step you might be taking in setting up your project that's causing the problem.

MrTAToad

Can you make the project available ?


MrTAToad

It compiles fine here too - it should be fine with XCode (as long as the mm file is included too).

aroldo

#11
MrTAToad and marovada,

Thank you.

I moved the .mm file to the Class folder in the XCode project and now I have different errors in the .mm file that I have to fix.

See attachments.

[a http://apd-games.com/][img http://apd-games.com/images/APDGames135.png][/a]
MacBook Pro OS X El Capitan
XCode Version 7
iPhone 6 running  iOS 9
iPad Mini running  iOS 7.1
Galaxy S5
Dell Latitude Windows 8 Enterprise
Palm Pre, Palm Pre2

MrTAToad

I haven't compiled for iPhone for a very long time, but I think you need to change the processor selection to ARM6 or something...

marovada

It builds fine for me.  Here is my project:

https://www.dropbox.com/s/cz0i8npet59ngxf/XCode.zip

What version of xcode do you have?

DaCarSoft

As I said here:

http://www.glbasic.com/forum/index.php?topic=8544.msg79309#msg79309
http://www.glbasic.com/forum/index.php?topic=8544.msg78455#msg78455
http://www.glbasic.com/forum/index.php?topic=6463.msg79429#msg79429 (sorry, it is in spanish)

There are problems with GLBasic and last version of Xcode. I fixed it (making my own Xcode project), but I suppose Gernot/Hello Kitty knows it (because I usually haven't replies to my comments from anyone, feeling that they are not understood or ignored) and I suppose that these problems will be solved in future versions of the "so called" beta 11.
"Si quieres resultados distintos... no hagas siempre lo mismo" - Albert Einstein.