How to hide the constants I defined in static library? - ios

I have a library of my own. And there are lots of constants defined in headers (for example animation duration). But, all my headers are visible and changeable. How can I prevent others to change my default values?
There are some const value in headers of Apple libraries like this:
CA_EXTERN NSString * const kCATransitionMoveIn
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);

Objective-C is still, well, C. Maybe older systems had issues, which is why you see the macros there. Anyway, you should still be safe with any built-in type.
If you declare something as "extern" the compiler will treat it something like, "OK, I see that someone has declared and external thingy. I don't have to know what it is, because some external unit will define it. The linker will handle the rest.
That paragraph will get me in trouble with the C-police, but it's close enough for a practical explanation. Thus, you can do this in your header file...
extern int const TheAnswerToLifeTheUniverseAndEverything;
And then, in one of your implementation files (outside of the #implementation/#end section)...
int const TheAnswerToLifeTheUniverseAndEverything = 42;
Note, in "modern" Xcode versions, you can do the same thing with objects. Note the "const" which means we have a constant-pointer-to-NSString.
// In header
extern NSString * const TheAnswerToLifeTheUniverseAndEverythingString;
// In source
NSString * const TheAnswerToLifeTheUniverseAndEverythingString = #"42";

Related

Getting the address of a section with Clang on OSX/iOS

For quite a while I've been using linker sections for registering elements that are used at runtime. I find that it's a simple way to make generic and extensible interface. A particularly useful use-case is something like unit tests or a multitool (e.g. busybox) so one can do something like:
$ ./tool <handler>
Where handler is a simple string that is "looked up" at runtime by walking the linker section. In this way, your parser doesn't have to "know" what commands are supported. It just finds their handlers in the linker section dedicated for them or it doesn't.
With GCC I've been doing something like (you can do this with Clang as well):
#define __tool __attribute__((__section__("tools")))
Then each handler I want to register gets a simple structure (with more or less information as needed)
struct tool {
const char *name;
const char *help;
int (*handler)(int argc, char **argv);
}
Then, for each tool you just do something like (often conveniently wrapped in a macro):
int example_tool0(int argc, char **argv)
{
return -1;
}
static const struct tool example_tool0 = {
.name = "exmaple_tool0",
.help = "usage: ...",
.handler = example_tool0
};
__tool static const struct tool *ptr = &example_tool0;
And used a such:
$ ./tool example_tool0
And because of __tool, each pointer registered in this way is packed into a linker section that can be walked.
Now, on GCC the linker creates two magic variables for each section: __start_SECTION and __stop_SECTION. So, to "walk" all of our registered handlers you just take the size of this section, divide by the size of a pointer, and then strncmp against the name (in this example) in the struct.
All of the above just to say, how can this be done using the OSX/iOS Clang-based toolchain? I would rather not use a custom linker script to achieve this seemingly simple operation.
Is there a way do this on OSX? I have worked around the issue by registering an empty entry at the beginning of the section and at the end. But doing so requires forcing the link order of the object files.
While OSX/iOS uses Clang as their platform compiler, they do not use the LLVM linker. Rather, they implement their own ld64 (which is open source) for whatever reason. So, it may just not be supported. I didn't readily see anything in man ld on OSX, but it's a bit info-dense.
For reference with ELF and GCC
And so this has been answered by others already. I did search, but I must have missed this answer. I've actually looked for an answer to this question many times before but must've never used the right words.
https://stackoverflow.com/a/22366882/2446071
In summary, apparently the linker supports syntax to define these desired symbols yourself:
extern char __start_SECTION __asm("section$start$SEGMENT$SECTION");
extern char __stop_SECTION __asm("section$end$SEGMENT$SECTION");

Which is the best in context of memory management in objective c to define constants

My project contains more that 5000 constants over the classes, I want to reduce the memory for those constants. So my doubt is which is the best way to use to define the constants in Objective-C.
#define
or
const
I think the best method to solve your task is using #define directive. Define directive doesn't use memory in the runtime. This directive is executed by a compiler.
Example:
#define MY_CONSTANT #"Hi"
Using in code:
NSString* string = [MY_CONSTANT stringByAppendingString:#" Mac"];
Here you can read about memory allocation for const variables.
Just expanding one of my comments above. The question is
#define MYSTRING #"This is a string"
versus say
NSString *const myString = #"This is a string";
The actual outcome is tool specific. However, examining a binary generated from Xcode, one will find the following:
As expected, both strings must be encoded in the binary, in this case, they will be the __TEXT __cstring as can be verified by running otool -v -s __TEXT __cstring BINARYNAME
Contents of (__TEXT,__cstring) section
0000000100002f19 This is a string
Keep in mind that this technically consumes memory, as the __TEXT is very much loaded into memory during runtime. The larger question, which is related to what the OP was asking is along the lines of "what additional memory outside of __TEXT is incurred by using const".
Remember that the linker will optimize multiple instances of a string. In other words:
NSString *const string1 = #"I'm a string";
NSString *const string2 = #"I'm a string";
will only result in one instance of that string in __cstring in the final binary.
So the overhead of using NSString * seems to be at least a pointer reference. This will be placed either in the __DATA __data or __DATA __const section depending on how it is defined:
NSString *const myString = #"This is a string";
Which would yield:
0000000100003068 (__DATA,__const) non-external (was a private external) _myString
NSString *myString = #"This is a string";
Which would yield:
0000000100003d60 (__DATA,__data) non-external (was a private external) _myString
Note that NSString *const is the way you should be defining it.
So assuming a 64-bit target, your 5,000 string overhead as a const would at least be 40,000 bytes or ~39K. I say at least in case there is some other hidden thing that is being done. But in general, I would expect the pointer to just point to the string in memory.
For most apps, this is probably not very large in the scope of things. So the question one should be asking is what advantages are there for using const?
And for that aspect, I'll save typing and refer you to the following links. It is preferred to use const as the compiler can type check.
Objective-C : #define vs extern const
#define vs const in Objective-C
It actually depends upon case to case. For your case i think #define seems to be a better option.
As far as I know:
For #define --> No memory access. As token_string will be substituted for each occurrence of identifier, exe size increases(storage of literal).
For const --> memory will be hit for every access of variable, extra exe size increases(storage of variable and storage of literal which is pointed or referred by variable).
For better understanding, please visit following links
"static const" vs "#define" vs "enum"
and static const vs #define

How is static const different from extern const?

In my iOS/Objective C projects, I often have a constants.h file with my API keys and such. Until today, I've been declaring my constants as static const like so:
static NSString * const kAPIKey = #"wembvkejrvb43789gvbiu2bvfake";
This works fine, but with the unfortunate downside that I can only create constants for primitives and NSString literals, essentially. Other objects, such as UIColor objects, cannot be stored in this constant as they cannot be initialized with a static literal syntax (my understanding, citation required).
After reading some C++ docs, I understand a few things:
The static is unnecessary, as const are implicitly static.
Calling NSString * const x is actually declaring a constant and immutable value in x. I cannot change the value, but may be able to change what x points to.
This const has internal linkage, meaning the the value is defined right away (presumable at compile time).
Are these conclusions correct?
How does an extern const differ? I assume they are externally linked (thus the extern keyword). Are they defined at run time? Can I create some sort of dynamic extern const that can be set with a value returned by a class method?
For example, I would like to create a globally-scoped constant that contains a UIColor value. I would like to construct this color value using the [UIColor colorWithRed:green:blue:alpha:] class method. This clearly doesn't work with the internally linked constants I've been using (I'm assuming because it happens at compile-time) - but is it possible using an external constant, possibly set up in the +initialize method?
Any elaboration on the details of this behavior would be immensely helpful.
The static is unnecessary, as const are implicitly static.
No, that's not true.
static when used at file scope (i.e. outside any method or function) means that the variable is visible only within that file.
extern means that the variable is defined in some other file.
const means that the variable cannot be modified.
Consider strings. Often, you'll have an implementation file (name ends in .m) that defines some constant string pointer:
NSString *const SomeString = #"some string";
You might want to use that same constant from other files. If so, you could add a declaration to the header (name ends in .h) file that explains to the compiler that the variable is defined elsewhere:
extern NSString *const SomeString;
and that would let you use SomeString in any file that imports the header file. On the other hand, you might decide that you definitely do not want the constant used outside the implementation file. In that case, you could declare it static (in the implementation file again):
static NSString *const SomeString = #"some string";
and that would prevent its use from outside the file.
Calling NSString * const x is actually declaring a constant and immutable value in x. I cannot change the value, but may be able to change what x points to.
Right, it declares the pointer x to be constant -- you can't change it. You also can't change the value that it points to if it's actually a NSString because an instance NSString isn't mutable.
This const has internal linkage, meaning the the value is defined right away (presumable at compile time).
I'll take the 5th on that -- I'm not sure exactly how the compiler deals with constant strings. I think it's safe to use that as a mental model, though; the string will in any case be defined before your code ever gets to use it.
On your specific programming question, how to create a compile-time defined color object: you can't, because, apart from the handful for which the language supplies literal syntax, objects are created at runtime.
But you can still do it elegantly at runtime, without any addition to global scope, the same way the sdk does...
#interface UIColor (RainbowAddition)
+ (UIColor *)chartruseColor;
#end
#implementation UIColor (RainbowAddition)
+ (UIColor *)chartruseColor {
// bonus: this is really chartruse... according to the internet
return [self colorWithRed:0.5 green:1.0 blue:0.0 alpha:1.0];
}
#end
http://cloford.com/resources/colours/500col.htm
Objective-C is a pure extension of C, C++ is not.
At global scope:
in C (and Objective-C) writing const is equivalent to extern const (external linkage);
in C++ writing const is equivalent to static const (internal linkage).
Both in C (and Objective-C) and C++, to create a global-scoped const you can define it, just one time, in one source file like extern const TYPE identifier = VALUE; and declare it (typically in an header file) like: extern const TYPE identifier; (read it: I defined this const elsewhere at global linkage level).

CF_IMPLICIT_BRIDGING_ENABLED non-functional in xcode5?

The WWDC 2013 lecture slides contain a section that in some cases the explicit bridging casts can be omitted. I wrote this in Xcode 5 (using 10.8 though, not 10.9), and the compiler complains I need a bridging cast. Am I just totally not understanding the concept?
#import <Foundation/Foundation.h>
CF_IMPLICIT_BRIDGING_ENABLED
CFStringRef MyCreateStringFromNothing();
CF_IMPLICIT_BRIDGING_DISABLED
void SomeFunction() {
// compiler requires bridging cast here...
NSString* x = MyCreateStringFromNothing();
}
The reason I ask is I wanted to write:
NSString* s = CFUUIDCreateString(NULL, uuid);
and thought that the new work on implicit bridging should simply enable me to write this. But this also needs a bridging cast.
This appears to be sort of black magic, but from my experiments functions with "Create" in them don't work with implicit bridging.
When I compiled this:
CF_IMPLICIT_BRIDGING_ENABLED
CFStringRef MyCreateStringFromNothing();
CFStringRef MyGetStringFromNothing();
CF_IMPLICIT_BRIDGING_DISABLED
void SomeFunction() {
NSString *const fails1 = MyCreateStringFromNothing();
NSString *const fails2 = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("FOO"));
NSString *const works = MyGetStringFromNothing();
}
The first two fail but the third one "works."
Note that implicit bridging apparently STILL does NOT actually keep the compiler from warning you about converting CFStringRef to NSString *, it just stops requiring you to insert a __bridge as well.
You'll notice that in slide at WWDC2013 in session 404 at 50:30, he uses CFDictionaryGetValue(), which returns a "void *", so it's one of the few functions that won't raise a warning. Any of the CF functions that return an actual type (e.g. CFStringRef, or CFDictionary) are still going to throw warnings, so, meh.
Check the compiler settings on the project and/or target. If this is an older project, you might have a stray option there causing you to use an older compiler. (This tripped me up a few times when I moved to Xcode 5 and wanted to use the latest Obj-C newness.)
These days, I always choose "Default compiler" in my build options.

Loading GLSL shader without using any Apple APIs

What is a good way to load a GLSL shader using C/C++ without using Objective-C or any Apple APIs?
I am currently using the following method, which is from the iPhone 3D Programming book, but it says that it is not recommended for production code:
Simple.vsh
const char* SimpleVertexShader = STRINGIFY
(
// Shader code...
);
RenderingEngine.cpp
#define STRINGIFY(A) #A
#include "Simple.vsh"
// ...
glShaderSource( shaderHandle, 1, &SimpleVertexShader, 0 );
If you want to load your shaders from files in your app bundle, you can get the file paths using the NSBundle object (in Objective-C), or using the CoreFoundation CFBundle object (in pure C).
Either way, you are using Apple-specific APIs. The only thing you're getting by using CFBundle instead of NSBundle is more boilerplate code.
If you don't want to use any Apple APIs, then your options are to embed your shaders as literal strings, or connect to a server on the Internet and download them (using the Unix socket API).
What you really need to do is define an interface by which your RenderingEngine gets the source code for its shaders, and implement that interface using the appropriate platform-specific API on each platform to which your port the RenderingEngine. The interface can be something super simple like this:
RenderingEngineShaderSourceInterface.h
#ifdef __cplusplus
extern "C" {
#endif
// You are responsible for freeing the C string that this function returns.
extern char const *RenderingEngine_shaderSourceForName(char const *name);
#ifdef __cplusplus
}
#endif
Then you create RenderingEngineShaderSource_Windows.cpp, RenderingEngineShaderSource_iOS.m, RenderingEngineShaderSource_Linux.cpp, etc. Each one implements RenderingEngine_shaderSourceForName using the appropriate API for that platform.
I use one of two methods. If it's a short shader, I may just put it code:
const char shader[] =
"uniform vec4 blah;\n" // Note, no semicolon here - it does the right thing
"main ()\n"
"{\n"
...rest of code
"}\n";
Or, if it's longer or going to be re-used in other places, I'll put it into a text file in the resources and read the text file at run time. You can get to it via [NSBundle pathForResource:ofType:].
Consider a C++ raw string literal; no STRINGIFY is needed since the newer features of C++ allow you to do similar things without macro.
I'd retype a good example but here is one.

Resources