extern in objective-C; do they behave differently than C? - objective-c

I required to share a const value between two files; so rather than keeping a magical number I decided to use a const variable.
So I created a global variable const int viewTag = 100; in my appDelegate.m
Then accessed it as extern const int viewTag; but I got following linker error:
Undefined symbols for architecture i386:
"viewTag", referenced from:
-[xxxViewController launchxxx] in libxxx_iPad.a(xxxViewController.o)
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
But the above thing is perfectly leagal in normal C,C++ env. can anybody throw some light?
Update: putting extern const int viewTag; in header and importing that header works, but I really don't want to do that for a single const int

Try putting:
extern const int viewTag;
in appDelegate.h, then importing this header where you need access to viewTag.

Another way is to use #define viewTag 100 in .pch file.
But I think, the best way is to create .h file with constants and include where you want

Related

Linker error for global variable [duplicate]

This question already has answers here:
Accesing global variable giving linker error in objective C
(2 answers)
Closed 9 years ago.
I'm making a small, simple application, so I decided to use global variables over Singletons. I'm also only using one.
My app pulls an int from a small preference file, and that is set to the global variable as an NSInteger. The global variable may be changed while the app is running.
AppController.h
#import <Cocoa/Cocoa.h>
extern NSInteger preferenceNumber;
#interface ....
App Controller.m
-(void)someMethod {
...
//fileContents is a string containing the int that is inside the file
preferenceNumber = [fileContents intValue]
...
}
The Linker Errors (2):
Undefined symbols for architecture x86_64:
"_preferenceNumber", referenced from:
-[AppController someMethod1] in AppController.o
-[AppController someMethod2:] in AppController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The bolded parts are the two errors.
What is causing this? What is the simplest, best way to solve it?
Just add one line in your implementation class:-
AppContollr.m
#implementation AppContoller
NSInteger preferenceNumber;

Add constants issues Xcode 4.5

I've got a class for storing constants.
So, there are two files that call Constant.h and Constant.m
This is what I have in .h file:
#import <Foundation/Foundation.h>
enum kParams {
kFirstName = 0,
kLastName = 1
};
extern NSString * const kNotificationUpdateMainMenu;
This is what I have in .m file:
#import "Constants.h"
NSString * const kNotificationUpdateMainMenu = #"kNotificationUpdateMainMenu";
For first time it works good, but when I try to add some other const (kNotificationFbLoginSuccsess for example) other classes don't see it.
This is a message that shows me which problem I have. But I don't understand how my other constants work without this issue (just new constant that I add get this error).
/Users/developer/Documents/Projects/Test/Test/Test/AppDelegate.m:121:64: Use of undeclared identifier 'kNotificationFbLoginSuccsess'
I found some way how to fix it:
Open organizer
Clear derived data
Delete project.xcworkspace file and xcuserdata
Close Project
Relaunch Xcode
but as I think is too much operations that I can add one constant. How come?
Your "global" constant is not actually external (separately compiled and later linked together). Take the easy way out and place NSString * const kNotificationUpdateMainMenu = #"kNotificationUpdateMainMenu"; into the header file. The method file needs nothing.
I would use #define kNotificationUpdateMainMenu #"kNotificationUpdateMainMenu" to perform the spell checking. The compiler will create one shared instance of the constant string for the entire compilation.

I am having all the time this issue after running my app

I don't know why, but after a while working without problems I added some buttons, then I launched my app and this error appeared:
ld: duplicate symbol _x in
/Users/alexbarco/Library/Developer/Xcode/DerivedData/RecolectaDatos-ayjpqqcajbhuzvbkvernzsyunpbe/Build/Intermediates/RecolectaDatos.build/Debug-iphonesimulator/RecolectaDatos.build/Objects-normal/i386/SeconViewController.o
and
/Users/alexbarco/Library/Developer/Xcode/DerivedData/RecolectaDatos-ayjpqqcajbhuzvbkvernzsyunpbe/Build/Intermediates/RecolectaDatos.build/Debug-iphonesimulator/RecolectaDatos.build/Objects-normal/i386/ViewController.o
for architecture i386 clang: error: linker command failed with exit
code 1 (use -v to see invocation)
Whenever I have duplicate symbol errors, it is almost always because I have a circular #import in my headers. The solution is quite simple, use forward declarations where possible, and #import .h files from .m files instead.
There are just two cases where you need to #import one .h from another:
if you are extending the class in the #import
you are implementing a protocol in the #import
Specifically, you do not need to import files just to use a class name or protocol in your signatures; instead use forward declarations.
For example, this (in Bar.h):
#import "Foo.h"
might become this (Bar.h):
#class Foo;
#protocol FooDelegate;
and bar.m:
#import "Foo.h"
Here is a link to the documentation on forward declarations.
The "duplicate symbol" message means that you're declaring some name (in this case, _x) twice in the same scope. Say you had code like this:
int _x = 1;
int _x = 2;
You'd expect to get an error then, right? You can use the same name for two things at the same time.
The error you're getting is essentially the same. You're declaring _x somewhere, and from the compiler's point of view you're doing it twice. There are a few ways to deal with this, depending on what _x represents.
chrahey's answer explains about forward class declarations. I won't cover that again here except to say that a forward declaration helps you resolve circular references, where the definition of class A depends on class B and vice versa.
If _x is a variable, it's likely that you're trying to declare it in a header file. The compiler basically copies the contents of each header file that you import into the source file, so if you declare a variable in a header file and then import that header into two or more implementation files, you'll end up with multiple declarations of that variable. To get around that, use the extern keyword to tell the compiler "this name will be declared somewhere else" and then put the real declaration in an implementation file:
Foo.h:
extern int _x;
Foo.m
int _x;
Pretty much the same thing goes for functions. It doesn't appear that _x is a function, but if it were, and if you were silly enough to put the function definition in a header file, then you'd again get an error if that file were imported into more than one implementation file. This is why header files contain prototypes, not definitions:
Foo.h:
int foo(int a);
Foo.m
int foo(int a)
{
return a + 10;
}

Linker error on const values

I am trying to create some string constants so I have the following:
Constants.h
extern NSString* const CONSTANT_ONE;
Constants.m
NSString *const CONSTANT_ONE = #"CONSTANT_ONE";
SomeOtherFile.m
#import "Constants.h"
... snip
NSString* something = CONSTANT_ONE;
Constants.m is listed in the "Compile Sources" bit of the target's build phases and is a member of the target when I look in its "Target Membership" section of the sidebar.
When I try to compile I get an error like:
Undefined symbols for architecture i386:
"_CONSTANT_ONE", referenced from:
-[SomeOtherFile someMethod:] in SomeOtherFile.o
I think I might be misunderstanding something basic here - can anyone help me with this error please?
The code in my initial question was correct. I don't know why but simply closing and re-opening Xcode solved the problem and it built fine. Just Xcode getting itself confused.

Calling C from Objective C

I'm new to objective c & c. I'm trying to use this random generator c library in an objective c program. My understanding is that objective c is a strict superset of c so this should be possible.
My code compiles and runs but I get a lot of warnings.
warning: implicit declaration of function 'mt_seed32'
warning: implicit declaration of function 'mt_lrand'
warning: Semantic Issue: Implicit declaration of function 'mt_seed32' is invalid in C99
warning: Semantic Issue: Implicit declaration of function 'mt_lrand' is invalid in C99
warning: Semantic Issue: Incompatible integer to pointer conversion initializing uint32_t * (aka unsigned int *) with an expression of type int
I have not imported the C header file to the objective c class - it just finds it. If I import it I get duplicate method errors.
C library header file:
extern void mt_seed32(uint32_t seed);
extern uint32_t mt_lrand(void);
Code to call it: [I've tried calling it with [self method()] but that crashes
mt_seed32(3);
uint32_t *i = mt_lrand();
Can anyone tell me how too get rid of these warnings?
The last compiler error happens because mt_lrand(); returns an int, not a pointer to an int. Therefore, the last line should be
uint32_t i = mt_lrand();
All the other errors are due to the fact that you did not #include the library header. Could you please post the errors that occur when you do include the library header?
Messages such as implicit declaration of function 'mt_seed32' usually pop up, when you use a function before it was defined. See example.
void foo() {
//do stuff
bar(); //call bar that was declared later
}
void bar() {
...
}
This may happen if you forgot to include the header file, or you included it after you used functions declared in that header file. Another fix is to declare a function prototype before usage.
Also you assign your random number to a pointer to uint32_t. Is this what you really want?
If not, then you must remove * from your declaration: uint32_t i = mt_lrand();
Was able to fix my problem by changing file type from '.m' to '.mm'. This causes the compiler to use obj c++ not obj c. It removes the warnings but I'm not sure if I've fixed the underlying issues
Solution – Duplicate Symbol