Call Static Method with C Syntax in Obj-C? - objective-c

I could redo this method using proper Obj-C syntax, but I was wondering how to call this from Obj-C. The method looks like this
#interface YarMidiCommon : NSObject
static
MIDIPacketList *makePacketList(Byte *packetBuffer, const UInt8 *data, UInt32 size);
#end
but I have no idea how to call that method. I have tried
Byte packetBuffer[size+100];
MIDIPacketList *packetList = makePacketList(packetBuffer, bytes, size);
but the error is "has internal linkage but is not defined." Is this possible without resorting to "proper" Obj-C syntax?
For the record, the method that I want to emulate would be something like
+ (MIDIPacketList*) makePacketListWithPacketBuffer:(Byte*)packetBuffer data:(const UInt8 *)data size:(UInt32)size;
which is verbose and annoying, seeing as everything here is C anyway.
This is related to this other answer I got today.

Since the function is a C function you need to remove the static keyword or else it will not be visible outside of its translation unit. Once you do that the first example you have will work. Also since it is a C function placing its declaration inside or outside of the #interface and definition inside or outside of the #implementation makes no difference on how you will call it.

Consider the declaration as being equivalent to static C function in the global scope. This is much unlike C++ or Java. There is no class scope or external linkage for this function.
As such, the #interface scope would not be a good place to declare makePacketList. The message means the definition is not visible when you use it.

You need to move the function to the .m (makes sense if you use it from this file only) or remove the static keyword.

Related

Objective c and struct

I have this problem. This the external library that i must use in .h file:
typedef struct _IPCSSContext IPCSSContext;
IPCSSContext * ipcssnew(const IPCSSCfg *_config, const IPCSSCallbacks *_callbacks, void *_user);
How can I use? Thanx
First you define a variable of type IPCSSCallbacks whatever that might be, but it's probably a struct of function pointers.
Then you fill in the fields of the variable with pointers to your callback functions.
Then you call icssnew() passing the IPCSSCallbacks, the config and a pointer to anything you like. This pointer will be passed untouched to your callback functions when they are called and you can do what you like with it in the callbacks (including nothing).
This is a pretty standard pattern in C for performing callbacks.

Equivalent of public static final variables

I understand that placing the word extern before a variable declaration in a header file declares the existence of a global static variable without initialising it. I also understand that if I import the file containing the extern variables, I can reference them without a class/file name. But where does one define them and their values?
What I am trying to do is create a class of constants with global constants that I want to use throughout an iOS application's code.
Does one put them inside the interface like this?
Example.h
#import <Foundation/Foundation.h>
#interface Constraints : NSObject
{
extern NSString * const PREFS_NAME;
}
Or does one put then outside of the interface like this
Example.h
#import <Foundation/Foundation.h>
extern NSString * const PREFS_NAME;
#interface Constraints : NSObject
{
}
Then in the implementation .m file how would one initialise the extern values?
Inside the implementation area like this?
Example.m
#import "Constraints.h"
#implementation Constraints
/**PRefecences name for the application**/
const NSString * PREFS_NAME = #"MyApp_Prefs";
#end
Or do initialise them outside of the implementation area like this:
Example.m
#import "Constraints.h"
/**PRefecences name for the application**/
const NSString * PREFS_NAME = #"MyApp_Prefs";
#implementation Constraints
#end
Or do I provide them their initial values in a constructor? or some arbitrary a static style method with + in front of it i.e. +(void) setAppConstraints;
I have tried several combinations, but always run into errors, such as "Redefinition of 'xVariable' with a different type". Or a something about "extern does not have an initialise interface" (or something like that, I forget). So I want to know how to declaire and initialise them properly to form the same role as public static final variables in Java.
Also what are the limits of the extern command? I know I can extern an NSInteger or NSString, but what about NSArray?
I am asking this question because there seems to be to much misleading, or incomplete, information regarding the use of extern in Objective-C. Many of the answers seem speculatory. My hope is for this question to be a good resource not only for me, but to limit further similar questions about the basics of extern.
You define it's value in the file inside which it's declared, which in your case is Example.m; You can still re-assign this variable, so the declaration in Example.h would look like this:
extern NSString * PREFS_NAME;
This way every file that imports Example.h has access to this variable. The equivalent of public static final in Objective-C is const. If you also want it to be public you should make it be a class instance variable, but in this case you don't need it because it's already accessible everywhere. So in this case it would be:
// .m file
NSString* const PREFS_NAME = #"MyApp_Prefs";
// .h file
extern NSString* const PREFS_NAME;
Also notice that const NSString* is different from NSString* const. The latter is a const pointer to NSString. The former hasn't sense even if it's a correct syntax. In Objective-C the const qualifier doesn't affect objects, instead there are mutable and immutable classes. It would have sense in C++ meaning that you can use just const methods on the instance.
extern is used to signal the compiler that you will be using a variable or a function that is defined in another compilation unit.
When you say extern const NSString *PREFS_NAME, you're saying "Replace all references in this compilation unit to PREFS_NAME to the variable PREFS_NAME as it is defined in another file." So when you try to assign PREFS_NAME in your .m, all you're doing is trying to assign a variable that, though it has a name, it doesn't exist. Declaring a variable extern is only a declaration of a variable or function, not a definition of that variable or function. It lets the compiler know that the name is in use, and that the linker will take care of what to do with it, but even if you provide a type here, it doesn't actually set aside space for the variable, it's expecting the space to be set aside in the compilation unit that's actually defining the variable.
You compile three or four different source code files together, three of them may declare:
extern int buffer[];
And one may declare
int buffer[BUFSIZE];
In its global scope, and the linker's job is to resolve the three declared references to extern buffer to the fourth's actual definition of the buffer.
extern is to C variables and functions much as #class is to Objective-C classes, it's a forward declaration, a promise to the compiler that you don't have to freak out when you see a name that's undefined here, because the linker will answer whatever lingering questions you may have.

Does __attribute__((const)) work on Objective-C method with Clang?

__attribute__((const)) is a GCC attribution to check purity of the function execution.
I think this is being supported on Clang, but when I put this to a method, it doesn't seem to work.
#interface C1
- (id)method1 __attribute__((const));
#end
int a = 0;
#implementation C1
- (id)method1 __attribute__((const))
{
a++;
return nil;
}
#end
The code above doesn't generate any warning or error.
Is this attribution working on Clang? Or what should I do to make this to work?
The const attribute doesn't check the purity of the function. It declares the purity of the function, so the optimizer can eliminate calls to the function. It's up to you to actually make sure the function is pure.
Declaring a method const can not work in Objective-C because it contradicts the runtime's message passing mechanism. The documentation for const says:
Note that a function that has pointer arguments and examines the data pointed to must not be declared const.
Every Objective-C method has at least one (implicit) pointer argument: self. It is always examined as part of message passing (objc_msgSend()). That's what makes Objective-C dynamic.

Using function pointer member variables within an Objective-C Class

(New to Objective-C, but well versed in C/C++).
Presently I have an Objective-C class and a number of its member variables will be function pointers. These function pointers will only be modified by the class itself, but may be used by other classes.
I'm not sure how to set up access to said function pointers.
The solution I currently envision is to declare said function pointers #public, which as I understand it will allow me to call them using the -> operator. This seems fairly unsatisfactory to me, since the function pointers are left open to meddling, and it flies in the face of sound OOP.
My next inclination is toward using #property, and declaring them read only. This seems more sane. I assume I'd call them using the dot operator, as the idea of using to getter to get the function pointer and then call it seems entirely ludicrous.
Can one use function pointers as properties? If so, how would I go about declaring these to be properties:
void (*sort)(SET, int) ;
char *(*toASCII)(CARD) ;
I have a feeling I'm missing a slight nuance to declaring these as properties.
I believe you should be able to use function pointers as properties. You'd do it like this:
#property (nonatomic, readonly) char *(*toASCII)(CARD);
And then in your implementation:
#synthesize toASCII;
Then
object.toASCII();
In your #interface:
#property(readonly) void (*sort)(SET, int);
#property(readonly) char *(*toASCII)(CARD);
In your #implementation:
#synthesize sort, toASCII;
In your init method (or wherever else you want to set the function pointers):
sort = someFunction;
toASCII = someFunction;
On modern versions of iOS, you don't even need to add an ivar (it gets added automatically for you when you do #synthesize).

What class of Objective-C variable is this?

I am working my way through some Objective-C code that I did not write and have found a variable declaration style that I am unfamiliar with. Can anyone tell me the scope of the variable 'myVar' in the class implementation below? Note that this appears in the '.m' file and not the interface declaration.
#implementation MyClass
#synthesize ivar1, ivar2;
NSString* myVar; // <- What is the intent?
- (id)init {
...
#end
To me the intention appears to be similar to that of a member variable. What are the advantages of declaring a variable in this way instead of using an ivar in the #interface declaration?
It's just a plain old global variable. There's only one instance of it, and it can be accessed by any code within the same file translation unit (the final file you get after running the preprocessor). Other translation units (that is, other .m files) can also access that global variable, but in order to do so, they need to use an extern statement:
extern NSString *myVar;
extern says "this is the name of a global variable, but it's defined in a different translation unit". The linker resolves all of the extern declarations at link time.
a poorly named global variable...
I'm not too experienced in ObjC but I'd say that is a global.