c struct implementation in iOS - objective-c

SSharedAppState.h
#import <Foundation/Foundation.h>
enum {
SharedCompletedStepNone = 0,
SharedCompletedStepOne = 1 << 0,
SharedCompletedStepTwo = 2 << 1,
SharedCompletedStepThree = 3 << 2
};
typedef NSUInteger SharedCompletedSteps;
#interface SSharedAppState : NSObject
{
struct {
unsigned int sharedCompletedStepMask:3;
} _appFlags;
}
#property (assign, nonatomic) SharedCompletedSteps sharedCompletedStep;
+(id)sharedInstance;
#end
SSharedAppState.m
#import "SSharedAppState.h"
#pragma mark - C functions
#pragma mark - Interface Extension
typedef struct _appFlags AppFlags;
#interface SSharedAppState ()
#property (unsafe_unretained, nonatomic) AppFlags *appFlags;
-(void *)newAppFlags;
#end
#pragma mark - Implementation
#implementation SSharedAppState
#synthesize appFlags;
#pragma mark - Iniitalizer
-(id)init
{
self = [super init];
if (self) {
// appFlags = (AppFlags *)malloc(sizeof(_appFlags));
appFlags = (AppFlags *)newAppFlags();
appFlags->sharedCompletedStepMask = 0;
appFlags.sharedCompletedStepMask = 0;
}
return self;
}
+(SSharedAppState *)sharedInstance
{
static dispatch_once_t onceToken;
static id sharedInstance;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
#pragma makr - Struct _appFlags
-(void *)newAppFlags
{
AppFlags *instance = (AppFlags *)malloc(sizeof(_appFlags));
return instance;
}
#end
Questions
appFlags = (AppFlags *)newAppFlags();
gives implicit declaration of function newAppFlags is invalid in C99
appFlags->sharedCompletedStepMask = 0;
appFlags.sharedCompletedStepMask = 0;
Incomplete definition of type 'struct _appFlags'
Member reference type 'AppFlags *' (aka 'struct _appFlags *') is a pointer; maybe you meant to use '->'?
Gives following warnings and error.
These is my first time to post questions here so please advice on html or editing. Thankyou!

When you write like this
struct {
unsigned int sharedCompletedStepMask:3;
} _appFlags;
you are declaring a variable _appFlags of an unnamed struct.
you probably meant
struct _appFlags {
unsigned int sharedCompletedStepMask:3;
};
or you could write
typedef struct _appFlags {
unsigned int sharedCompletedStepMask:3;
} AppFlags;

Related

What's happening when you synthesize a subclass' variable?

I have a superclass and a subclass. I can access the variable some_property (declared in the superclass) via self.some_property in the subclass.
However if I try to access the instance variable directly with _some_property, I'll get the error 'Use of undeclared identifier _some_property...'.
Using #synthesize some_property = _some_property silences this warning.
Whats going on when I re-synthesize the property?
You are creating another ivar named _some_property — and also overriding the getter method to return the value of this new ivar. The compiler gives you an error about this if the base class's #implementation (i.e. the implicit declaration of its _some_property ivar) is visible at the site of the #synthesize in the subclass.
(By the way, don't do this!)
You can demonstrate to yourself by inspecting the Obj-C runtime:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#interface Base : NSObject
#property id foo;
#end
#interface Derived : Base
#end
#implementation Derived
#synthesize foo=_foo; // the compiler doesn't know about Base's _foo yet, so this is OK...
- (instancetype)init {
if ((self = [super init])) {
_foo = #"I'm derived";
}
return self;
}
#end
#implementation Base // after Derived to avoid the error
- (instancetype)init {
if ((self = [super init])) {
_foo = #"I'm base";
}
return self;
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Derived *obj = [Derived new];
NSLog(#"getter returns %#", obj.foo);
unsigned int count = 0;
// Examine Base ivars
NSLog(#"Base ivars:");
Ivar *ivars = class_copyIvarList([Base class], &count);
for (unsigned int i = 0; i < count; i++) {
NSLog(#" %s = %#", ivar_getName(ivars[i]), object_getIvar(obj, ivars[i]));
}
// Examine Derived ivars
NSLog(#"Derived ivars:");
ivars = class_copyIvarList([Derived class], &count);
for (unsigned int i = 0; i < count; i++) {
NSLog(#" %s = %#", ivar_getName(ivars[i]), object_getIvar(obj, ivars[i]));
}
}
return 0;
}
Output:
getter returns I'm derived
Base ivars:
_foo = I'm base
Derived ivars:
_foo = I'm derived

Wrapping a C API in Objective-C

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).

how to create and allocate a C buffer as part of an objective C class

best to explain with an example:
in my AudioItem.h
#define ITEM_CAPACITY 100
typedef struct DataStruct {
void * content;
UInt32 size;
} DataStruct;
typedef DataStruct *DataStructRef;
#interface AudioItem : NSObject
{
DataStructRef data;
}
#property (assign, readwrite) DataStructRef data;
in AudioItem.m
#synthesize data;
-(id)initWithID:(NSString *)itemID
{
self = [super init];
data->content = malloc(ITEM_CAPACITY);
return self;
}
The above code looks a lot like this one, but I get a BAD_EXEC_ERROR.. how come? The reason why I would like to use a C buffer rather than some NSMutableData or whatever is b/c I've tried using NSMutableData and I feel like it's slowing down my real time application
it fails because data is a null pointer when you set its content.
the easy way to do this is:
enum { ITEM_CAPACITY = 100 };
typedef struct DataStruct {
char content[ITEM_CAPACITY];
UInt32 size;
} DataStruct;
#interface AudioItem : NSObject
{
#private
DataStruct data;
}
#implementation AudioItem
- (id)initWithID:(NSString *)itemID
{
self = [super init];
if (0 == self) return;
data.size = ITEM_CAPACITY;
return self;
}

Request for member 'pData' with BOOL value TRUE is not a structure or union-Objective C

I could not use the pData[4096] to pass it to the other function from main.
data.m
------
#implementation data
static int msgID;
static char pData[4096]="\0";
+ (void)initialize
{
//some initialisations
msgID =123;
}
-(void)SwapEndian:(uint8_t*)pData withBOOLValue:(BOOL)bIsAlreadyLittleEndian
{
NSLog("%s %s",pData,bIsAlreadyLittleEndian);
}
#end
main.m
-------
[dat SwapEndian:dat.pData withBOOLValue:TRUE];
I am getting pData undeclared. As pData is declared as static inside the Data
implementation i tried with dat.pData to pass it from main.But when i do it i am getting
Request for member 'pData' with BOOL value TRUE is not a structure or union.
It is difficult to determine what the code is supposed to do, but here is how to create an Objective-C object that holds an integer identifier and a 4096-character array. Please note that this sort of thing is usually discouraged. Unless you have a really specific reason for using int and char[], the identifier should be NSInteger and the data should be an NSData or NSString object.
I have also used some of the "standard" naming conventions. If you are writing Cocoa code, it helps to drink a lot of the Kool-Aid.
Message.h:
#interface Message : NSObject
{
int identifier;
char data[4096];
}
#property (nonatomic, assign) int indentifier;
#property (nonatomic, readonly) char * data;
- (void)swapEndian:(BOOL)flag;
#end
Message.m:
#implementation Message
#synthesize identifier;
#synthesize data;
- (id)init
{
if ((self = [super init]) == nil) { return nil; }
identifier = 0;
data[0] = '\0';
return self;
}
- (void)swapEndian:(BOOL)flag
{
NSLog(#"%s %d", data, flag);
}
#end
main.m:
#import "Message.h"
...
Message * message = [[[Message alloc] init] autorelease];
message.identifier = 123;
[message swapEndian:YES];

static behaviour->objective C

I have this static declaration of m_pData=1099656 in a class.
In main NSLog(#"Testing:%d",m_pData);
Its printing me 0.
How to get the same value of m_pData in the class in the main function too.
I cant use obj.m_pData or obj->m_pData to acces the variable.
EDITED:
test2.m
----------
#import <Foundation/Foundation.h>
#import "data_derived.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
data* dat = [data alloc];
requestSession* session = [requestSession alloc];
[session init];
[dat TxCreateImage:RM_REQUEST_SESSION];
NSLog(#"Testing:%d",m_pData); //the static variable is not printing the value its holding.Its printing Zero.If printed the same variable inside the class it gives some numbers.
[dat dataBuffer:&m_pData withLen:&m_uDataSize]; //here the actual values of static values are not passed.when printed both of them contains zero values.
[pool drain];
return 0;
}
data.h
--------
#import <Foundation/Foundation.h>
#import "remote.h"
static int m_nMessageId; //Message ID
static int m_uSessionId; //Session ID
static int m_chSequenceChar; //Sequence ID
static int* m_pData; //Integer buffer to carry data
static int m_uDataSize; //Datasize
#interface data : NSObject {
#public
}
- (id)initWithID:(int) uMessageId withData:(id)pData withSize:(size_t) uDataSize;
+ (void)initialize;
- (void)dealloc;
- (id) dataBuffer:(int**)m_Data withLen:(int**)uLen;
- (BOOL) TxCreateImage:(int)messageId;
#end
data.m
---------
#import "data.h"
#define ENCODED_MSG_DATA_OFFSET 8
#implementation data
+ (void)initialize
{
m_uSessionId = 0;
m_chSequenceChar= 0;
// Initialize values from derived class
m_nMessageId = 0;
m_pData = 0;
m_uDataSize = 0;
}
- (id) initWithID:(int) uMessageId withData:(id)pData withSize:(size_t) uDataSize
{
if(self=[super init])
{
// Initialize the member variables
m_uSessionId = 0xFF;
m_chSequenceChar= 10;
// Initialize values from derived class
m_nMessageId = uMessageId;
m_pData = (int*)pData;
m_uDataSize = (int)uDataSize;
}
NSLog(#"Data size:%d",uDataSize);
NSLog(#"m_pData:%d",m_pData);
NSLog(#"pData:%d",pData);
return self;
}
- (id) dataBuffer:(int**)m_Data withLen:(int**)uLen
{
if ( m_uDataSize <= RMH_MAX_ENCODED_LENGTH )
{
int abBigEndian[RMH_MESSAGE_MAX_SIZE];
memcpy(abBigEndian,m_Data,m_uDataSize);
NSLog(#"m_Data:%d",*m_Data);
NSLog(#"abBigEndian:%d",abBigEndian);
uLen += ENCODED_CRC_BYTE_LEN + 1;
NSLog(#"%d",*uLen);
}
NSLog(#"END!");
return self;
}
- (BOOL) TxCreateImage:(int)messageId
{
char pData[4096];
sprintf(pData,"%x %d %d %d %x",ASCII_STX,m_uSessionId,m_chSequenceChar,m_nMessageId,ASCII_ETX); //uLen = ENCODED_MSG_DATA_OFFSET;
NSLog(#"%s",pData);
return YES;
}
- (void)dealloc
{
[super dealloc];
}
#end
data_derived.h
---------------------
#import <Foundation/Foundation.h>
#import "data.h"
#define DECLARE_RS232_NEWMSG(ClassID)\
enum \
{ \
ID = ClassID \
}; \
#interface requestSession : data {
#public
DECLARE_RS232_NEWMSG(RM_REQUEST_SESSION);
struct RMH_REQUEST_SESSION_MSG st;
}
-(id)init;
-(void)dealloc;
#end
data_derived.m
---------------------
#import "data_derived.h"
#implementation requestSession
- (id)init
{
size_t asize = sizeof(st);
st.uDeviceID = RS232_PROTOCOL_DEVICE_ID;
st.uProtocolVersion = RS232_VERSION;
memset(st.uReserved,0x00,sizeof(st.uReserved));
NSLog(#"Address of the structure:%d",&st);
self=[super initWithID:ID withData:(id)&st withSize:asize];
if (self) {
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
#end
Don't place your static members in .h file. Move them to data.m.
Also about static keyword - in C (and Objective C, which is clear superset to C), when using static with global variables (like you do), it only indicates that this variables will be local to the file you declared these variable in. So global variables anyway have only one instance, with static modifier or without. If you don't use static, then you can access these variables from other files with external declaration, like:
// file1.m
int variable = 4;
// file2.m
external int variable; // variable == 4
That's why your code is printing you 0. m_pData in test2.m is not the same m_pData you have in data.m. Without static modifier you would get a linker error.
And you might want to write getters/setters for static members. Like:
+ (int *)pData {
return m_pData; // or smth like memcpy
}