I just started learning "accessor methods" on Objective C and I get stuck. I couldn't find why I am getting that "Duplicate Symbol Error" that stops the program from running. Should be a easy thing! but I will appreciate some help.
The xCode issue navigator complains:
Ld /Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Products/Debug/Shapes-Object normal x86_64
cd "/Users/leo/Google Drive/Documentos/FormaciĆ³n/Curso iOS/Pre iOS, pilares/Learn Objective C on the Mac/Ejercicios/Chapter 06/SPLIT 04.02 Shapes-Green-Circles MAS FACIL"
export MACOSX_DEPLOYMENT_TARGET=10.7
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk - L/Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Products/Debug -F/Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Products/Debug -filelist /Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Intermediates/Shapes-Object.build/Debug/Shapes-Object.build/Objects-normal/x86_64/Shapes-Object.LinkFileList -mmacosx-version-min=10.7 -fobjc-link-runtime -framework Foundation -Xlinker -dependency_info -Xlinker /Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Intermediates/Shapes-Object.build/Debug/Shapes-Object.build/Objects-normal/x86_64/Shapes-Object_dependency_info.dat -o /Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Products/Debug/Shapes-Object
duplicate symbol _colorPrint in:
/Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Intermediates/Shapes-Object.build/Debug/Shapes-Object.build/Objects-normal/x86_64/main.o
/Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Intermediates/Shapes-Object.build/Debug/Shapes-Object.build/Objects-normal/x86_64/Circulo.o
duplicate symbol _colorPrint in:
/Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Intermediates/Shapes-Object.build/Debug/Shapes-Object.build/Objects-normal/x86_64/main.o
/Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Intermediates/Shapes-Object.build/Debug/Shapes-Object.build/Objects-normal/x86_64/SALCHICHA.o
duplicate symbol _colorPrint in:
/Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Intermediates/Shapes-Object.build/Debug/Shapes-Object.build/Objects-normal/x86_64/main.o
/Users/leo/Library/Developer/Xcode/DerivedData/Shapes-Object-ctkpgnxalegjsdbbylyuaqxtisrd/Build/Intermediates/Shapes-Object.build/Debug/Shapes-Object.build/Objects-normal/x86_64/Shape.o
ld: 3 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
That is my main():
#import <Foundation/Foundation.h>
#import "Circulo.h"
#import "SALCHICHA.h"
void FuncionDibujarFormas (id Formas[], int count)
{
for (int i = 0; i < count; i++) {
id shape = Formas[i];
[shape Dibujar];
}
} // FuncionDibujarFormas
// --------------------------------------------------
// The main function. Make the shapes and draw them
int main (int argc, const char * argv[])
{
id Formas[3];
Formas[0] = [Circulo new];
[Formas[0] definirColor: kRojo];
Formas[2] = [SALCHICHA new];
[Formas[2] definirColor: kVerde];
FuncionDibujarFormas (Formas, 3);
return (0);
} // main
That is the "superclass" header for Shape.h:
#import <Foundation/Foundation.h>
typedef enum {
kRojo,
kVerde,
} Color;
//--------------------------------------------------
NSString *colorPrint (Color switchColor) //"Color" se asigna "switchColor"
{
switch (switchColor) {
case kRojo:
return #"rojo";
break;
case kVerde:
return #"verde";
break;
}
return #"malign#";
} // colorPrint
#interface Shape : NSObject
{
Color RellenarColor;
}
- (void) definirColor: (Color) RellenarColor;
- (void) Dibujar;
#end // Shape
That's the Shape.m:
#import "Shape.h"
#implementation Shape
- (void) definirColor: (Color) ImplementationRellenarColor
{
RellenarColor = ImplementationRellenarColor;
} // definirColor
- (void) Dibujar
{
} // draw
#end // Shape
That's the "childclass" Circulo.h:
#import "Shape.h"
#interface Circulo : Shape
#end // Circulo
Thats the child class Circulo.m :
#import "Circulo.h"
#implementation Circulo
- (void) definirColor: (Color) ImplementationRellenarColor
{
if ( ImplementationRellenarColor == kRojo ) {
ImplementationRellenarColor = kVerde;
}
[super definirColor: ImplementationRellenarColor];
} // definirColor
- (void) dibujar
{
NSLog (#"dibujando un circulo %#", colorPrint(RellenarColor));
} // dibujar
#end // Circulo
That's "chilclass" SALCHICHA.h:
#import "Shape.h"
#interface SALCHICHA : Shape
#end // SALCHICHA
Thats chilclass SALCHICHA.m
#import "SALCHICHA.h"
#implementation SALCHICHA
- (void) dibujar
{
NSLog (#"dibujando una SALCHICHA %#", colorPrint(RellenarColor));
} // dibujar
#end // SALCHICHA
You have a C function implementation in a header file (Shape.h):
NSString *colorPrint (Color switchColor) //"Color" se asigna "switchColor"
Each time you import the header you duplicate the symbol.
So using in pure Objc you should have someting like:
In header:
+(NSString*)colorPrint:(Color)switchColor;
In implementation:
+(NSString*)colorPrint:(Color)switchColor {
switch (switchColor) {
case kRojo:
return #"rojo";
case kVerde:
return #"verde";
}
return #"malign#";
}
And to call it:
NSLog (#"dibujando un circulo %#", [Shape colorPrint:RellenarColor]);
Edit: Fixed parameter name
Related
I have an issue when implementing OpenCV's K-Nearest to Objective-C++
Below is my sample code for implementation:
BridgeClass.h
#ifndef BridgeClass_h
#define BridgeClass_h
#include <Foundation/Foundation.h>
#interface BridgeClass : NSObject
- (void)testFunction;
#end
#endif
BridgeClass.mm
using namespace ml;
typedef KNearest KNN;
#implementation BridgeClass{
KNN* kNearest;
}
- (id) init {
self = [super init];
if (self) {
kNearest = KNN::create();
}
return self;
}
- (void) testFunction {
BOOL test = kNearest->isTrained();
NSLog(#"Test: %d", test);
}
But when I called testFunction, it shows error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x400000048)
What is the problem with my implementation?
I've been tinkering all day, and I can't seem to fix this error.
Here's the code:
//
// main.m
// Learning ObjC
//
// Created by Nickirv on 8/9/15.
// Copyright (c) 2015 Nickirv. All rights reserved.
//
#import <Foundation/Foundation.h>
#interface Person: NSObject{
int age;
int weight;
}
-(void) print;
-(void) setAge: (int) a;
-(void) SetWeight: (int) w;
#end
And it outputs this issue:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I would appreciate any help! Thank you very much!
You can't delete the main boilerplate code:
int main(int argc, const char * argv[]) {
#autoreleasepool {
}
return 0;
}
In the end Objective-C is "C" and the program starts execution by calling main. Additionally Objective-C code needs to execute in an autoreleasepool.
You define class #interfaces and #implemtations outside of (generally above) the boilerplate but the first line of code to run must be within the autoreleasepool scope {}.
Here is an example Objective-C program similar to what the OP seems to want using #properties for simplicity and demonstration.
It is important to study Objective-C documentation until the following code is fully understood, td;dr does not work for this.
#import <Foundation/Foundation.h>
#interface Person: NSObject
#property int age;
#property int weight;
- (void)print;
#end
#implementation Person : NSObject
- (void)print {
printf("Age: %i, weight: %i", self.age, self.weight);
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Person *don = [[Person alloc] init];
don.weight = 130;
don.age = 23;
[don print];
}
return 0;
}
Output:
Age: 23, weight: 130
I'm making a simple test to see if I can run Objective-C on Linux without GNUStep, so I followed an example here on SO to get it running, here's my code:
//WSObject.h
#include <objc/runtime.h>
#include <stdio.h>
#interface WSObject
+ (id) alloc;
- (void) dealloc;
- (void) hello;
#end
//WSObject.m
#include "WSObject.h"
#implementation WSObject
+ (id) alloc {
return class_createInstance(self, 0);
}
+ (void) dealloc {
object_dispose(self);
}
+ (void) hello {
puts("Hello, world");
}
#end
//test.m
#include "WSObject.h"
int main(int argc, const char *argv[]) {
WSObject *obj = [WSObject alloc];
[obj hello];
[obj dealloc];
return 0;
}
When I then try to compile it with gcc test.m -o test -lobjc
I get the following error:
/tmp/ccDzvsol.o:(.data+0x80): undefined reference to `__objc_class_name_WSObject'
collect2: error: ld returned 1 exit status
Any help?
EDITED
I have been trying to start coding in Objective-c. Its just a simple program to try getter and setter methods. Also print Hello World. THe following is my code:
#import <objc/Object.h>
#interface Car:Object{
int wheel: 5;
}
- (int)wheel;
- (void)setWheel: (int)newWheel;
#end
#include <stdio.h>
#implementation Car
- (int)wheel{
return wheel;
}
- (void)setWheel: (int)newWheel{
wheel = newWheel;
}
#end
#include <stdlib.h>
int main(void){
printf("Hello World");
}
I now get garbage
/tmp/cc3UC6jY.o: In function `__objc_gnu_init':
hello.m:(.text+0x6d): undefined reference to `__objc_exec_class'
/tmp/cc3UC6jY.o:(.data+0x1c0): undefined reference to `__objc_class_name_Object'
collect2: error: ld returned 1 exit status
I used the the command gcc -o hello hello.m -lobjc
I have spent hours googling this answer.
The following variation of your code compiled and ran for me:
#import <objc/Object.h>
#interface Car : Object {
int wheel;
}
- (int)wheel;
- (void)setWheel: (int)newWheel;
#end
#implementation Car
- init {
wheel = 5;
return self;
}
- (int)wheel {
return wheel;
}
- (void)setWheel: (int) newWheel {
wheel = newWheel;
}
#end
#include <stdio.h>
int main(void){
printf("Hello World\n");
id myCar = [[Car alloc] init];
printf("Wheel value is %d\n", [myCar wheel]);
return 0;
}
I'm trying to wrap a C API in Objective-C but am getting EXC_BAD_ACCESS in objc_release.
Field.h:
#ifdef __cplusplus
extern "C" {
#endif
struct sc_field
{
char *title;
};
typedef struct sc_field sc_field_t;
sc_field_t* sc_create_field();
void sc_destroy_field(sc_field_t *field);
const char* sc_get_title(const sc_field_t *field);
void sc_set_title(sc_field_t *field, const char *title);
#ifdef __cplusplus
}
#include <string>
class Field
{
public:
explicit Field();
virtual ~Field();
std::string title() const;
void setTitle(const std::string &title);
private:
class Private;
Private *d;
};
Field.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Field.h"
sc_field_t* sc_create_field()
{
sc_field_t *field = (sc_field_t*)malloc(sizeof(sc_field_t));
field->title = (char*)calloc(1, sizeof(char));
return field;
}
void sc_destroy_field(sc_field_t *field)
{
if (field)
{
free(field->title);
free(field);
}
}
const char* sc_get_title(const sc_field_t *field)
{
if (!field)
{
fprintf(stderr, "%s: fatal error, field is NULL\n", __FUNCTION__);
return NULL;
}
return field->title;
}
void sc_set_title(sc_field_t *field, const char *title)
{
if (!field)
{
fprintf(stderr, "%s: fatal error, field is NULL\n", __FUNCTION__);
return;
}
field->title = (char*)realloc(field->title, sizeof(char) * sizeof(title));
strcpy(field->title, title);
}
SCField.h:
#import "Field.h"
#import <Foundation/Foundation.h>
#interface SCField : NSObject
{
#private
sc_field_t *field;
}
#property (nonatomic, copy) NSString *title;
- (id)init;
- (id)initWithTitle:(NSString *)title;
- (void)dealloc;
#end
SCField.m:
#import "SCField.h"
#implementation SCField
#synthesize title;
- (id)init
{
self = [super init];
if (self)
{
field = sc_create_field();
}
return self;
}
- (id)initWithTitle:(NSString *)aTitle
{
self = [self init];
if (self)
{
[self setTitle:aTitle];
}
return self;
}
- (void)dealloc
{
sc_destroy_field(field);
[super dealloc];
}
- (NSString *)title
{
return [NSString stringWithUTF8String:sc_get_title(field)];
}
- (void)setTitle:(NSString *)aTitle
{
sc_set_title(field, [aTitle UTF8String]);
}
#end
Test:
SCField *field = [[SCField alloc] initWithTitle:#"Hello world!"];
NSLog(#"%#\n", [field title]);
[field release];
The code seems to work fine until I release my SCField instance. If I remove the title and setTitle: implementations as if I were storing an NSString* directly in the SCField the code works fine (I tried assign instead of copy in the #property, too - no luck). What am I doing wrong?
I think the issue is that calling UTF8String will give you memory that will be autoreleased (according to the documentation).
Rather than using realloc() in sc_set_title(), just malloc() a new buffer and copy it. Also, your realloc() parameters are incorrect anyway, so it probably ends up being a no-op. You need to allocate strlen(title) + 1; sizeof won't do anything for you since you're just asking the compiler to give you 1 (sizeof(char)) * 4 bytes (sizeof(title) - a pointer).
Use getCString:maxLength:encoding:. To get length of string in bytes for a buffer, use lengthOfBytesUsingEncoding: (takes O(n) time) or maximumLengthOfBytesUsingEncoding: (takes O(1) time).