[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: CoreFoundation

From: Stef Bidi
Subject: Re: CoreFoundation
Date: Fri, 23 Oct 2009 20:14:35 -0500

On Fri, Oct 23, 2009 at 4:34 PM, David Chisnall <address@hidden> wrote:
Hi Stef,

Having an implementation of Core Foundation would be nice, but I believe your approach is wrong.

That is a definite possibility! :)

 These are the requirements I started out with:
* Successfully compile the EXRange example in CF-Lite's CFRuntime.h;
* Pass CF and NS objects freely (the ones that have corresponding NS classes, at least).

First, please do not use the info field in the class structure for anything.  That field is for the runtime to use.  The GCC runtime uses several of them, the GNUstep runtime uses a few more.  It should not be used; there is no guarantee that future runtime versions won't use them all.

I guess I should explain, I was only going to use the CLS_GETNUMBER() macro in objc-api.h (that is, only the top half of the info field).  I also noticed that this macros, when written out, doing: ((sizeof(long)*8)/2)... wouldn't ((sizeof(long)<<3)>>1) be a lot faster?  Specially on RISC archtectures?  My C programming book suggests that when multiplying or dividing by a multiple of 2^x a shift is often better than a multiply/divide.

With regard to the CFTypeID, this should be the address of the class structure.  For those unfamiliar with how CoreFoundation works:

That includes me... the only thing I have to go by is CF-Lite's CFRuntime.h and the CF docs.
Each of the CF classes has an isa pointer, just like an Objective-C object.  Unlike Objective-C objects, this is set to a value below 64KB, which is guaranteed not to be the address of a real class.  This number is the CFTypeID, which is a pseudo-class.

The reason that is that Apple's CoreFoundation does not depend on libobjc (although it does link to it).  If you use CF without libobjc, then you use static dispatch for all of the CF calls.  When you call CFSomething() the function checks that the object's isa pointer is set to the magic constant that it expects and if not then it calls another function (via some ugly macros).  This is done so CF objects can be used without relying on libobjc having finished loading classes.

If you use Objective-C then you get the toll-free bridging.  If you send a message to an object with an isa pointer that is less than 2^16, then the runtime uses a special lookup mechanism.  If you call a CF function with an object with an isa pointer above 2^16, it bounces it to the Objective-C runtime for looking up the method (this is how, for example, you can use CFString functions on your own NSString subclass).

Hmm... that's an interesting.

Unless you want to use CF for some very low-level stuff, then there is really no point in copying this.  You can just:

1) Define Objective-C classes that implement the CF types (many of these already exist in GNUstep).
2) Write wrapper functions that call the ObjC methods.
3) Return the address of the class as the isa pointer.

This will then work with all code that uses CF types unless they either rely on the TypeID < 2^16 thing or uses CF functions in +load or __attribute__((constructor)) functions.

Most of the CF equivalents of class methods take a CFAllocator.  You can declare this as a typedef from NSZone; they are functionally equivalent.  For a first pass, you can just implement most of the CF functions as trivial Objective-C functions, for example:

typedef NSArray *CFArrayRef;
typedef NSZone *CFAllocatorRef;

And here's where I ran into some problems... apparently, CFAllocatorRef is considered a class (responds to CFGetTypeID()), but isn't one in GNUstep.  Also, it allows users to define they're own with CFAllocatorCreate(), which takes a CFAllocatorContext.  I might just have to not allow that if this is the case.

CFArrayRef CFArrayCreateCopy(CFAllocatorRef allocator, CFArrayRef theArray)
       [(NSArray*)theArray copyWithZone: allocator];

I was going with objc_msg_lookup, I figured I could do everything in pure C that way.  But I guess this will work, too.  This is why I put it out at this stage, so I don't follow the wrong path for too long.

Once this is working, then you can start worrying about optimising it.  You might also consider making these in static inline functions in the header wrapped in #ifdef __OBJC__ so that people using CF functions in ObjC call the real methods.

I wrote some macros for declaring / defining these CF functions a while back, which I can send you if you're interested, and I'm happy to review any code you're working on.

Definitely, for both those statement!  I'll clean up what I have in CFRuntime.c and CFBase.c (I'm pretty sure only I can understand the mess in there), and have you take a look.

At this point, I'm really not sure what the correct way ahead should be.  I'm hoping I'll get some more feedback so that I can make an informed decision.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]