Is it generally valid that a macro is used to create a method name? I mean...actually it's just simple text replacement before the compiler actually runs, right?
Yes, it is valid; macro expansion occurs before the compiler even reads the code. The main limitation is that one cannot embed a preprocessor directive within a preprocessor directive. So, for example:
// This is ok:
#define PREFIX(X) this_name_is_prefixed_ ## X
// ...
- (void) PREFIX(doSomething):id;
// ...
// But this isn't:
#define IMPORT(X) #import X
IMPORT(<Foundation/Foundation.h>) // <= Don't expect this to work
With the exception of the "#import" directive, Objective-C's preprocessor is basically the same as the C preprocessor. (The "#import" is like "#include", except that #import implies include only once, so preprocessor guards are not required for headers that are included only with #import).
There is nothing that prevents that. It is even commonly used (though I don't know for the iphone), for instance, in device drivers implementation. In that case, macros are used to generate boilerplate code, and for this boilerplate to communicate with your code, you have to either guess the correct function names (not advised), or use generating macros, for example USB_ATTACH(uthum) to generate the signature of the attach method for the uthum driver.
Related
In Objective-C I had a bunch of compiler flags set in Build Settings -> Other C Flags that were being used in the code. For instance:
Flag => -DPortNumber = 1
And in code I was able to access it by #(PortNumber)
This doesn't work in Swift, and I'm not able to find an answer.
The -D flag to C compilers defines a preprocessor macro. There are no preprocessor macros in Swift. So if you're looking to do something like:
// compile with -DPORT_NUMBER 31337
var port = PORT_NUMBER // error
... you can't. Swift is designed for source code to be syntactically complete before compilation. If you could switch out blocks of it at build time, you'd break the ability of the toolchain to help verify that your code is correct. (Partly this is because preprocessor macros in C are textual replacement: you can use them to rewrite any part of the language, not just fill in values for variables.)
The Swift compiler does have a -D flag, but its use is more limited: you can use it for build configurations only. So, if you wanted to do something like the following, you'd be cool:
// compile with -DUSE_STAGING_SERVER
#if USE_STAGING_SERVER
var port = 31337
#else
var port = 80
#endif
Note that unlike C, everything inside an #if block needs to be syntactically complete. (For example, you can't put just the declaration line of a func in an #if block and leave the function body outside the conditional.)
Of course, this doesn't help you if you want to have a configuration value set at compile time be used in your code. For that, I'd recommend alternate approaches. Xcode can still do textual substitution in resource files, like property lists. (Note that the Info.plist that comes with your app is full of things like $(TARGET_NAME), for example.) So, you could include a bundle resource with your app whose contents are populated at compile time according to your project settings, then read your port number from that.
I added the line extern "C" void perlinTest(void); to a C++ header along with the include of the c header file hoping that was all I needed but the compiler complains:
Undefined symbols for architecture i386:
"perlinTest()", referenced from:
CreateRenderer3(IResourceManager*) in Renderer.o
Your C++ code needs to be aware that the function is a C function. To do so, you need to declare it this way:
extern "C" [prototype];
A realistic example for your situation would be:
extern "C" void perlinTest();
The reason for this is that C++ function names are mangled to something that tells about the types of the parameters. At the lowest level, this is what allows overloading: it never really is legal to have two visible symbols that share the same name, so C++ allows them by embedding markers that indicate the types of the parameters in the function names. For instance, void perlinTest() gets mangled as _Z10perlinTestv on my Lion box with g++ (and probably clang++), though this is ABI-specific and will not necessarily be the same on other platforms.
However, C doesn't support overloading, and functions aren't subject to name mangling, so when your C++ code tries to call one, it needs to know that it must not use a mangled name. This is what extern "C" tells the compiler.
If your header files need to be readable from both C and C++, the common practice is to wrap them in an extern "C" block (extern "C" { /* declarations */ }) itself wrapped in an #ifdef __cplusplus preprocessor directive (so the C code doesn't see the extern "C" code).
#ifdef __cplusplus
extern "C" {
#endif
/* header body */
#ifdef __cplusplus
}
#endif
If it is not a library, you do not need any extern C. Iwould be turning to the .c file extensions and how your compiler is configured to recognize it (looks like not as .c code)
Have you actually implemented void perlinTest(void) anywhere?
Initially, you'll likely be able to merely declare the function without actually having to implement it. If none of your other classes/objects actually call perlinTest(), Xcode will gladly build and run your app, and not issue any errors. Since perlinTest() isn't actually referenced from anywhere, it doesn't care that the function isn't actually implemented.
As soon as you attempt to call perlinTest() from one of your other classes (like from CreateRenderer3(IResourceManager*) in Renderer.o), the linker will want to make sure that symbol can be resolved, and if you haven't actually implemented a barebones definition of it (see below), then you'll likely get an error like the one you got.
A minimal implementation like the following should prevent the linking error:
void perlinTest(void) {
}
One trick you can use to debug this is to introduce an intentional error in your perlinTest() function. Then build your app and see if the compiler reports the error. If the app compiles anyway, then your problem is that the file that has this function is not part of the target you are building.
Also note that the error that you pasted is for a i386 architecture, so it can't be iPhone. You are probably building for the iPhone simulator instead.
Edit: next step would be to check that the link command issued by Xcode includes the .o that has the C function. If it does, then you should dump the contents of the .o file with the nm utility, to see what the function name looks like in the .o.
I have added some debugging code to my app which I want to call only when needed. I remember there is some kind of IFDEF that can be used to conditionally include code into a source file.
For example I might have something like this:
IFDEF kDebugEnabled == YES {
// some debugging code here
}
And then this piece of code is only compiled into the binary if that kDebugEnabled is YES.
How can I do something like this?
Please note: I don't want to use the project compiler flag settings. I just want to define a BOOL (or something that serves the purpose just as well) which is true or false and then just easily set it in my App Delegate for example. I find it hard to navigate to the project compiler settings, searching for a flag and then setting it. I know there is a Debug flag which might be of use.
What you are looking for is:
#ifdef __YOURSYMBOL__
<conditional code>
#endif
You can programmatically define __YOURSYMBOL__ like this:
#define __YOURSYMBOL__
__YOURSYMBOL__ can be any string that makes sense to you to remember why you are including/excluding that code snippet.
The DEBUG constant is a special preprocessor constant that the compiler defines specifically for you when the code is built for debugging, so you can simply use it:
#ifdef DEBUG
<conditional code>
#endif
Take into account that this is the C-preprocessor, not C, nor Objective-C that you are using, so a test like kDebugEnabled == YES (where kDebugEnabled is an Objective-C variable) is simply not possible. You can define integer values for your constants, like this:
#define __LOG_LEVEL__ 3
and then test for it:
#if __LOG_LEVEL__ == 3
...
Endif
As far as I know, you can't have code in your classes that is not compiled into the final product without using compiler flags. However, using the DEBUG flag is a lot easier than you think. If you are using Xcode 4, it's set up for you by default.
#ifdef DEBUG
// Your debug-only code goes here
#endif // DEBUG
Xcode has, by default, two configurations, Debug and Release. When you use the debug build configuration, among other things, it sets the DEBUG compiler flag, which you can then use to conditionally compile code. No need to mess with compilation settings at all.
What is the importance of .pch file and what is the significance of"#ifdef OBJC"?
Also, where do we define parameters like "#ifdef IS_PRODUCTION" which are checked in .pch file.
The .pch file allows you to avoid importing common files like UIKit.h and Foundation.h. If you have those files imported in the .pch, your own classes don't need to import them.
The significance of #ifdef OBJC is so that you don't import headers containing objective-c code if you don't have the compiler set to build objective c code (hence avoiding lots of compiler errors).
You define parameters such as IS_PRODUCTION inside the target's build settings. I do it usually in "other C flags".
.pch is a Pre-Compile Header.
In the C and C++ programming languages, a header file is a file whose text may be automatically included in another source file by the C preprocessor, usually specified by the use of compiler directives in the source file.
#ifdef OBJC lets the compiler know that the code is Objective-C.
#ifdef IS_PRODUCTION is something you have defined on your own, a directive telling the compiler to do something only if this is defined, most-likely something for a PRODUCTION build.
I just found two piece of code
#if CONSOLE // defined by the console version using
ournamespace.FactoryInitializer;
#endif
and
#if _NET_1_1
log4net.Config.DOMConfigurator.ConfigureAndWatch(new System.IO.FileInfo(s) );
#else
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(s) );
#endif
Can any one please tell me with a running sample( please provide a simple one) what is the significance of those code snippets and when and how to use those?
Thanks.
Sure. These refer to conditional compilation symbols which can be defined at compile-time and which control what code is actually built. Here's an example:
using System;
class Test
{
static void Main()
{
#if FOO
Console.WriteLine("FOO was defined");
#endif
#if BAR
Console.WriteLine("BAR was defined");
#endif
}
}
If you compile this with
csc Test.cs
It won't print anything. If you compile it with
csc Test.cs /D:FOO
then it will print "FOO was defined" - and obviously the same is true for BAR.
Note that these aren't the same as C++ macros - a symbol is either defined or not; it doesn't have a "replacement value" as such.
In Visual Studio, you specify which symbols should be defined in the Build tab of the project properties. Additionally, at the very start of the file you can explicitly define and undefine symbols:
#define FOO
#undef BAR
This can be important when calling methods decorated with ConditionalAttribute - such calls are ignored by the compiler if the appropriate symbol isn't defined. So if you wanted to make sure that all your Debug.Print calls came through even if you hadn't defined the DEBUG symbol for the rest of the project, you could use:
#define DEBUG
...
Debug.Print("Foo");
Personally, I don't use all this very much. Aside from anything else, it makes it easier to understand the code if you know that it will all be compiled and run at execution time.
EDIT: Just to clarify a little on terminology - #if, #line, #pragma etc are all preprocessor directives; FOO and BAR (in this case) are the conditional compilation symbols.
They're used for conditional compilation.
If CONSOLE (known as a conditional compilation symbol) is defined for the first example with #define CONSOLE, the code within #if CONSOLE and #endif will be compiled and built into the assembly, otherwise the compiler ignores the code within them.
Undefining a conditional compile symbol is via #undef e.g #undef CONSOLE. The language specification also states :
There is no requirement that
conditional compilation symbols be
explicitly declared before they are
referenced in pre-processing
expressions. Instead, undeclared
symbols are simply undefined and thus
have the value false.
Those are called preprocessor directives. Quote from the docs:
'#if' lets you begin a conditional directive,
testing a symbol or symbols
to see if they evaluate to true. If
they do evaluate to true, the compiler
evaluates all the code between the #if
and the next directive.
So basically when you compile your program with /define:symbol switch it will either evaluate the if statement or not. For example:
csc foo.cs /define:DEBUG
allows you to define the DEBUG directive and enter the #if DEBUG branch. Remember that contrary to the if statement those are purely compile time and the body of the else statement won't even be included in your compiled assembly.
Your project can have multiple configurations, the most common are Debug and Release.
In Debug mode you can output debug strings, do additional checking etc.
For example:
void a(int x){
#if DEBUG
System.Diagnostics.Debug.WriteLine("a("+x+")");
#endif
//Do stuff.
}
You can define directives project-wide in the project's properties and make debug/release builds, or you could make an application that uses different libraries for some output (OpenGL/XNA). Or as you have, #if _NET_1_1 checks if a symbol _NET_1_1 is defined, assuming that .NET FX 1.1 is used, and uses proper classes, so you can target multiple framework versions in multiple project configurations.