Objective-C error: initializer element is not constant - objective-c

Why does the compiler give me the following error message on the provided code: "initializer element is not constant". The corresponding C/C++ code compiles perfectly under gcc.
#import <Foundation/Foundation.h>
const float a = 1;
const float b = a + a; // <- error here
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
NSLog(#"Hello, World!");
[pool drain];
return 0;
}

That code will only compile correctly if the const float statements appear somewhere other than the file scope.
It is part of the standard, apparently. It is important that all file-scope declared variables are initialised with constant expressions, not expressions involving constant variables.
You are initialising the float 'b' with the value of another object. The value of any object, even if it is a const qualified, is not a constant expression in C.

#dreamlax is correct, you can't have a const declaration whose initialization depends upon another (const) variable. If you need one to depend on the other, I suggest creating a variable that you can treat as a constant and initialize it only once. See these SO questions for details:
Defining a constant in objective-c
Constants in Objective C

I don't have Xcode on my machine here so I can't try my example,
But can you try
#define A (1)
#define B (A + A)
const float a = A;
const float b = B;

Related

Pass Objective-C block or method as C-function pointer

I'm using https://github.com/nodejs/http-parser, the callbacks it uses are like this
struct http_parser_settings {
http_cb on_message_begin;
http_data_cb on_url;
http_data_cb on_status;
http_data_cb on_header_field;
http_data_cb on_header_value;
http_cb on_headers_complete;
http_data_cb on_body;
http_cb on_message_complete;
/* When on_chunk_header is called, the current chunk length is stored
* in parser->content_length.
*/
http_cb on_chunk_header;
http_cb on_chunk_complete;
};
The main callback type is defined here
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
I'm trying to find a way to pass either an Objective-C block or method as the function pointer in the parser_settings. However it lets me use only a C-function, which doesn't suit me because I also need to access the state of an Objective-C object in the callback
At the moment my solution is as follows:
int onHeaderField(http_parser* _, const char* at, size_t length) {
// Need to access state here, so doesn't work for me as a c function
char header[length];
strncpy(header, at, length);
NSLog(#"Header %s", header);
return 0;
}
...
- (void)method {
http_parser_settings settings;
settings.on_header_field = onHeaderField; // rather than func would like to set a block/method to capture and access self
size_t nparsed = http_parser_execute(self.parser, &parserSettings, charData, messageLength)
}
How would I go about accessing self from the callback passed to http_parser_execute?
Technically you can "extract" an Objective-C method implementation in form of a C-pointer with use of class_getMethodImplementation, however these implementations have objc_msgSend-like signature and always require the receiver as an argument, thus not really usable outside of Objective-C world:
NSString *str = #"Hollow World";
SEL sel = #selector(isEqualToString:);
Method meth = class_getInstanceMethod([str class], sel);
typedef BOOL(*IsEqualToStringPtr)(NSString *, SEL, NSString *);
IsEqualToStringPtr impl = (IsEqualToStringPtr)method_getImplementation(meth);
NSLog(#"Is equal? %#", impl(str, sel, #"Hello, World!") ? #"YES" : #"NO"); // prints "NO"
NSLog(#"Is equal? %#", impl(str, sel, #"Hollow World") ? #"YES" : #"NO"); // prints "YES"
Having that said, neither blocks nor Objective-C methods are directly convertible to a C function pointer (they are pointers to structures under the hood), especially when you want to complement it with any kind of context/state.
The simplest thing you can do is to use a global/statically allocated block variable which can be accessed from a C function without altering it's signature:
static int(^StaticBlock)(http_parser *parser, const char *at, size_t length);
static int my_callback(http_parser *parser, const char *at, size_t length) {
return StaticBlock(parser, at, length);
}
...
- (void)someObjectiveCMethod {
__weak typeof(self) weakSelf = self;
StaticBlock = ^(http_parser *parser, const char *at, size_t length) {
if (!weakSelf) {
return -1;
}
__strong typeof(weakSelf) strongSelf = weakSelf;
strongSelf.mprpty += length;
NSLog(#"Hello from Objective-C");
return 8;
};
http_parser_settings settings;
settings.on_header_field = my_callback;
}
The only viable alternative I can think of is using C++ lambdas. However it's still a big challenge when you need to access current state/context, let alone it will require you to switch to Objective-C++. If you are ok with it, first you need to rename your Objective-C file from SomeClass.m into SomeClass.mm. This way you tell Clang that the source code is Objective-C++ now and the compiler should accept a C++ code. Next, if your C library doesn't have C++ guards, you may want to wrap the C includes with extern "C" expression (otherwise linker would not be able to locate C symbols, because C++ mangles them):
extern "C" {
#include <c_header.h>
}
Now the tricky part: lambda expressions return special objects, closures, which can be seamlessly converted to C function pointers only if they don't capture anything from surrounding context. In our scenario it's not the case and it will require extra steps to convert it to a C pointer. Add this code somewhere in your *.mm file:
template<typename L>
struct c_functor_factory : c_functor_factory<decltype(&L::operator())> {};
template<typename R, typename F, typename ...Args>
struct c_functor_factory<R(F::*)(Args...) const> {
using pointer = typename std::add_pointer<R(Args...)>::type;
static pointer make_cptr(F&& func) {
static F instance = std::forward<F>(func);
return [](Args... args) {
return instance(std::forward<Args>(args)...);
};
}
};
template<typename L>
inline static typename c_functor_factory<L>::pointer make_cptr(L&& lambda) {
return c_functor_factory<L>::make_cptr(std::forward<L>(lambda));
}
In fact this solution is not much far from the global C function solution I suggested above. When a closure is passed as an argument here, this template function just perfect-forwards it to a statically allocated variable. As a result the static closure can be called from a capture-less lambda, which in turn is converted to a C function pointer.
Finally, you can make use of C++ lambda expressions and pass them as C function pointers anywhere in your Objective-C code:
- (void)someObjectiveCMethod {
__weak typeof(self) weakSelf = self;
const auto cptr = make_cptr([weakSelf](http_parser *parser, const char *at, size_t length) {
if (!weakSelf) {
return -1;
}
__strong typeof(weakSelf) strongSelf = weakSelf;
strongSelf.num += val;
NSLog(#"Hello from Objective-C++, %s!", at);
return 32;
});
http_parser_settings settings;
settings.on_header_field = my_callback;
}
Unlike the previous one, C++ solution is much more reliable, because each time your code hits the lambda expression, it emits a new closure object. In both cases, however, the function objects have static storage duration, thus make sure you don't pass any strong pointer in the body of it (otherwise it will never be released).

C pointer array not recognized in Swift

I'm converting/importing some legacy code into Swift and I have to use a file of constants that look like this:
Constants.h
extern const int workingConstant;
extern int constantArray1[];
extern int constantArray2[];
extern int constantArray3[];
extern int *problematicConstant[];
Constants.m
const int workingConstant = 3;
int constantArray1 [] = {2,50,50,49,47,46,44,42,16,41,49,47,46,44,42,41,16,64,64,62,62,60,60};
int constantArray2 [] = {72,718,63,740,94,756,117,755,127,759,121,767,120,777,118,788};
int constantArray3 [] = {226,505,226,505,213,518,206,531,230,545,250,562,258,575,265,560,277,543};
int* problematicConstant [] = {constantArray1,constantArray2,constantArray3}
In my legacy Objective C code I can import the header and call a method like:
-(void)doStuff:(int)firstConstant paths:(int **)paths shrink_p:(CGAffineTransform *)shrink_p{
CGMutablePathRef hitPath = CGPathCreateMutable();
for(int i = 0; i < firstConstant; i++){
CGPathMoveToPoint(hitPath, &(*shrink_p), paths[firstConstant][i+1]);
}
}
that takes the workingConstant and the problematicConstant and is a method of a subview. My .swift UIView subclass successfully finds the workingConstant however the problematicConstant is throwing a "Use of unresolved identifier" error when I try to call doStuff on my subview.
I was able to reproduce your problem with some mock-up code. For whatever reason Swift can't see problematicConstant via the bridging header. However, I was able to circumvent this by adding yet another global variable:
extern int ** ppInt; // in the header
int ** ppInt = problematicConstant; // in the Objective-C implementation
The extern declaration and definition can go into the existing Objective-C source or, if you want to keep it clean, into separate header and implementation files. In fact, the extern can just be in the bridging header.
As an aside, the constantArray... declarations could not be bridged, either, but if you need them, you can do a similar trick:
int * pInt1 = constantArray1;
...

passing a value not defined in enum

I have a class named blender that has a single instance variable, speed. speed is of type enum BlenderSpeed defined as
typedef NS_ENUM(NSUInteger, BlenderSpeed)
{
BlenderSpeedStir=1 ,
BlenderSpeedCop=2 ,
BlenderSpeedCrush=3
} ;
The main.m is as below. Basically, I was expecting there to be a warning when I passed 5 as argument in the setSpeed message send since speed is only supposed to take on values 1, 2 and 3 per enum definition.
But I don't see any issues when I build and run the code. The speed gets set to 5 without any issues.
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
blender *myBlender = [[blender alloc] init] ;
[myBlender setSpeed:2] ;
NSLog(#"Current blender speeed = %lu",[myBlender speed]);
[myBlender setSpeed:5] ;
NSLog(#"Current blender speeed = %lu",[myBlender speed]);
}
return 0;
}
Any pointers will be greatly appreciated.

compare blocks and functions in objective C

As I am learning objective C, my understanding is new and incomplete. The concept of a block is very similar to a function. They even look almost identical:
FUNCTION named 'multiply'
#import <Foundation/Foundation.h>
int multiply (int x, int y)
{
return x * y;
}
int main(int argc, char *argv[]) {
#autoreleasepool {
int result = multiply(7, 4); // Result is 28.
NSLog(#"this is the result %u",result);
}
}
BLOCK named 'Multiply'
#import <Foundation/Foundation.h>
int (^Multiply)(int, int) = ^(int num1, int num2) {
return num1 * num2;
};
int main(int argc, char *argv[]) {
#autoreleasepool {
int result = Multiply(7, 4); // Result is 28.
NSLog(#"this is the result %u",result);
}
}
I found various statements on the web like:
"Blocks are implemented as Objective-C objects, except they can be put on the stack, so they don't necessarily have to be malloc'd (if you retain a reference to a block, it will be copied onto the heap, though). "
Ray Wenderlich says:
"Blocks are first-class functions"
I have no clue what all this means. My example shows that the same thing is accomplished as a block or a function. Can someone show an example where blocks can do something functions cannot? or vice versa?
Or is it something more subtle, like the way the variable 'result' is handled in memory?
or is one faster/safer?
Can either of them be used as a method in a class definition?
Thank you.
Blocks are Objective-C objects, and functions aren't. In practice, this means you can pass around a block from one piece of code to another like so:
NSArray *names = #[#"Bob", #"Alice"];
[names enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
NSLog(#"Hello, %#", name);
}];
In C, you can achieve similar effects by passing around pointers to functions. The main difference between doing this and using blocks, however, is that blocks can capture values. For instance, in the example above, if we wanted to use a variable greeting:
NSString *greeting = #"Hello";
NSArray *names = #[#"Bob", #"Alice"];
[names enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
NSLog(#"%#, %#", greeting, name);
}];
In this example, the compiler can see that the block depends on the local variable greeting and will "capture" the value of greeting and store it along with the block (in this case, that means retaining and storing a pointer to an NSString). Wherever the block ends up getting used (in this case, within the implementation of [NSArray -enumerateObjectsUsingBlock:]), it will have access to the greetings variable as it was at the time the block was declared. This lets you use any local variables in the scope of your block without having to worry about passing them into the block.
To do the same using function pointers in C, greeting would have to be passed in as a variable. However, this can't happen because the caller (in this case, NSArray) can't know (especially at compile time) exactly which arguments it has to pass to your function. Even if it did, you'd need to somehow pass the value of greeting to NSArray, along with every other local variable you wanted to use, which would get hairy really quickly:
void greet(NSString *greeting, NSString *name) {
NSLog(#"%#, %#", greeting, name);
}
// NSArray couldn't actually implement this
NSString *greeting = #"Hello";
NSArray *names = #[#"Bob", #"Alice"];
[names enumerateObjectsUsingFunction:greet withGreeting:greeting];
Blocks are closures -- they can capture local variables from the surrounding scope. This is the big difference between blocks (and anonymous functions in other modern languages) and functions in C.
Here's an example of a higher-order function, makeAdder, which creates and returns an "adder", a function which adds a certain base number to its argument. This base number is set by the argument to makeAdder. So makeAdder can return different "adders" with different behavior:
typedef int (^IntFunc)(int);
IntFunc makeAdder(int x) {
return ^(int y) { return x + y; }
}
IntFunc adder3 = makeAdder(3);
IntFund adder5 = makeAdder(5);
adder3(4); // returns 7
adder5(4); // returns 9
adder3(2); // returns 5
This would not be possible to do with function pointers in C, because each function pointer must point to an actual function in the code, of which there is a finite number fixed at compile time, and each function's behavior is fixed at compile time. So the ability to create a virtually unlimited number of potential "adders" depending on a value at runtime, like makeAdder does, is not possible. You would instead need to create a structure to hold the state.
A block which does not capture local variables from the surrounding scope, like in your example, is not much different from a plain function, aside from the type.

objective-c constants.h static const

I googled a lot of similar questions, but none of them had a really good answer about what i needed.
Im wondering about the best way to write constants in some .h file.
my constants file is just a clear file with no imports, just clear .h file. I import it in prefix file.
when i use
static NSInteger someInteger = 1;
or
static BOOl someBool = YES;
The compiler compiles okay but gives me a warning that this variable is unused even though im using it multiple times in different classes.
But if i use
static NSString* someString = #"";
there are not any warnings.
also if i use
const NSInteger someInteger = 1;
Compiler compiles okay for a real device, but when running on a simulator it does not compile with an error duplicate symbols for architecture i386
also what is the difference between
const NSString* someString = #"";
const NSInteger someInteger = 1;
and
NSString* const someString = #"";
NSInteger const someInteger = 1;
I ended up using static const NSInteger someInteger =1;, but i wonder if this is a right option.
So really my question is: what words should i use to successfully create a constants.h file?
For all types (both primitive or otherwise) then you need to provide a single implementation of it somewhere:
constants.h:
extern const int someValue;
extern NSString * const someString;
constants.m:
const NSInteger someValue = 1;
NSString * const someString = #"Some string";
You never want to use static variables in header files as you will end up with multiple copies of the "constant" in every implementation file that includes that header (they may not upset the linker, and cause a link error, but they are there).