CoreFoundation

View: New views
7 Messages — Rating Filter:   Alert me  

CoreFoundation

by Stef Bidi :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Just testing the water... I've been a little bored and started looking at implementing a portion of CoreFoundation on top of libobjc and GNUstep-base, I'm tentatively calling it CoreBase.

At this point I've spent most of my time on the runtime (CFRuntime) and CFBase.  I'm not sure if it works, because in CF the runtime requires CFString and CFDictionary and I'll have to at least do some work there before even trying to compile.  Because I don't want to have to rewrite/copy parts of what's already in GNUstep-base (like reference counting) I've decided to depend on it.  Libobjc is also required because I'm using that as a gateway to -base, and using some of it's features (like the class number stored in class->info to coinside with the CFTypeID).

Before continuing with it (because, of course, time is precious) I want to make sure there's at least some interest.  I'm also going to need a fairly high degree of help on this project because certain parts are out of my league (I still think it's an interesting learning experience).

Anyway, just let me know if it's a project I should keep moving forward.

Thanks
Stefan

_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@...
http://lists.gnu.org/mailman/listinfo/gnustep-dev

Re: CoreFoundation

by David Chisnall :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Stef,

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

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.

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

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

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;
CFArrayRef CFArrayCreateCopy(CFAllocatorRef allocator, CFArrayRef  
theArray)
{
        [(NSArray*)theArray copyWithZone: allocator];
}

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.

David

On 23 Oct 2009, at 21:23, Stef Bidi wrote:

> Just testing the water... I've been a little bored and started  
> looking at implementing a portion of CoreFoundation on top of  
> libobjc and GNUstep-base, I'm tentatively calling it CoreBase.
>
> At this point I've spent most of my time on the runtime (CFRuntime)  
> and CFBase.  I'm not sure if it works, because in CF the runtime  
> requires CFString and CFDictionary and I'll have to at least do some  
> work there before even trying to compile.  Because I don't want to  
> have to rewrite/copy parts of what's already in GNUstep-base (like  
> reference counting) I've decided to depend on it.  Libobjc is also  
> required because I'm using that as a gateway to -base, and using  
> some of it's features (like the class number stored in class->info  
> to coinside with the CFTypeID).
>
> Before continuing with it (because, of course, time is precious) I  
> want to make sure there's at least some interest.  I'm also going to  
> need a fairly high degree of help on this project because certain  
> parts are out of my league (I still think it's an interesting  
> learning experience).
>
> Anyway, just let me know if it's a project I should keep moving  
> forward.
>
> Thanks
> Stefan
> _______________________________________________
> Gnustep-dev mailing list
> Gnustep-dev@...
> http://lists.gnu.org/mailman/listinfo/gnustep-dev

-- Send from my Jacquard Loom



_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@...
http://lists.gnu.org/mailman/listinfo/gnustep-dev

Re: CoreFoundation

by Gregory Casamento :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey guys,

I'm currently working on porting webkit.  It would be very nice to
have an implementation of corefoundation in gnustep.

Currently I'm having to use opencflite.

GC

On Friday, October 23, 2009, David Chisnall <theraven@...> wrote:

> Hi Stef,
>
> Having an implementation of Core Foundation would be nice, but I believe your approach is wrong.
>
> 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.
>
> With regard to the CFTypeID, this should be the address of the class structure.  For those unfamiliar with how CoreFoundation works:
>
> 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).
>
> 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;
> CFArrayRef CFArrayCreateCopy(CFAllocatorRef allocator, CFArrayRef theArray)
> {
>         [(NSArray*)theArray copyWithZone: allocator];
> }
>
> 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.
>
> David
>
> On 23 Oct 2009, at 21:23, Stef Bidi wrote:
>
>
> Just testing the water... I've been a little bored and started looking at implementing a portion of CoreFoundation on top of libobjc and GNUstep-base, I'm tentatively calling it CoreBase.
>
> At this point I've spent most of my time on the runtime (CFRuntime) and CFBase.  I'm not sure if it works, because in CF the runtime requires CFString and CFDictionary and I'll have to at least do some work there before even trying to compile.  Because I don't want to have to rewrite/copy parts of what's already in GNUstep-base (like reference counting) I've decided to depend on it.  Libobjc is also required because I'm using that as a gateway to -base, and using some of it's features (like the class number stored in class->info to coinside with the CFTypeID).
>
> Before continuing with it (because, of course, time is precious) I want to make sure there's at least some interest.  I'm also going to need a fairly high degree of help on this project because certain parts are out of my league (I still think it's an interesting learning experience).
>
> Anyway, just let me know if it's a project I should keep moving forward.
>
> Thanks
> Stefan
> _______________________________________________
> Gnustep-dev mailing list
> Gnustep-dev@...
> http://lists.gnu.org/mailman/listinfo/gnustep-dev
>
>
> -- Send from my Jacquard Loom
>
>
>
> _______________________________________________
> Gnustep-dev mailing list
> Gnustep-dev@...
> http://lists.gnu.org/mailman/listinfo/gnustep-dev
>

--
Gregory Casamento
Open Logic Corporation, Principal Consultant
## GNUstep Chief Maintainer
yahoo/skype: greg_casamento, aol: gjcasa
(240)274-9630 (Cell), (301)362-9640 (Home)


_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@...
http://lists.gnu.org/mailman/listinfo/gnustep-dev

Re: CoreFoundation

by Stef Bidi :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, Oct 23, 2009 at 4:34 PM, David Chisnall <theraven@...> 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.

Stefan


_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@...
http://lists.gnu.org/mailman/listinfo/gnustep-dev

Re: CoreFoundation

by Richard Frith-Macdonald-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 24 Oct 2009, at 02:14, Stef Bidi wrote:

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

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

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.

Don't think that you have to build on top of base while leaving base untouched ... writing CF on top of base is the right thing to do, but that doesn't mean you can't modify base to make it easier ... in this case there's no reason you can't change NSZone to actually be a class rather than a struct.  

_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@...
http://lists.gnu.org/mailman/listinfo/gnustep-dev

Re: CoreFoundation

by Stuart Crook :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi.

I've done quite a bit of work with the source of Apple's CFLite  
(working with OpenCFLite, and as the basis of my Foundation clone  
PureFoundation) so I thought I'd just chime in here.

On 23 Oct 2009, at 22:34, David Chisnall wrote:

> With regard to the CFTypeID, this should be the address of the class  
> structure.  For those unfamiliar with how CoreFoundation works:
>
> 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.

Sorry, but this is incorrect. If a CF type is bridged to obj-C/
Foundation, then the ISA operates as in obj-C. If it is not bridged,  
or (as in CFLite) obj-C/Foundation classes are absent, this is NULL.  
The actual CFTypeID is stored in the block of header data which  
follows the ISA, and so is still present even if the ISA is set up as  
a pointer.

Under Apple's CoreFoundation/Foundation, the bridged classes are  
private end-of-tree subclasses. eg. for NSString, the class is  
NSCFString (it runs NSString -> NSMutableString -> NSCFString, and  
whether the NSCFString is mutable or not depends on how it was  
created, and is flagged internally). Their ivars start with the ISA  
and then there follows the block of CF-specific fields which I don't  
believe are mapped/accessible as ivars. If you look at the CFLite  
source, this is CFRuntimeBase structure defined in CFRuntime.h.

Which is all besides the point, because you're not looking to exactly  
clone Apple's CF here. So, Stef, your best approach is definitely, as  
David suggested:

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

You may also want to implement Apple's super-secret -
(CFTypeID)_cfTypeID method, which returns the CFTypeID of bridged  
objects.

_sjc_





_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@...
http://lists.gnu.org/mailman/listinfo/gnustep-dev

Re: CoreFoundation

by David Chisnall :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 24 Oct 2009, at 02:14, Stef Bidi wrote:

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

The CLS_GETNUMBER() macro should be considered private, and won't be  
exposed in future versions of the runtime.  With regard to your  
optimization question, you might be interested in my article How Not  
To Optimize:

http://www.informit.com/articles/article.aspx?p=1390173

In this case, if it is faster to use shifts then any compiler written  
in the last 20 years (including the toy that I wrote as an undergrad  
coursework assignment) will emit shifts for you.  However, because  
this is an expression where all values are known at compile time, the  
compiler will simply evaluate it at compile time and if you look in  
the generated assembly you will find that it has become either 16 or 32.

Note that, because shifts are relatively rare operations, most modern  
processors aren't optimized for shift-heavy instruction streams  
(except ARM, which lets you add a free shift to almost any  
instruction, which is pretty shiny).  Older versions of GCC would  
expand multiplications to sequences of shift and add instructions, but  
on a modern x86 chip this will be the same speed in the best case and  
slower in the worst.

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

You might be interested in this example, which talks in a lot more  
detail:

http://ridiculousfish.com/blog/archives/2006/09/09/bridge/

Don't pay too much attention to it though; you want to duplicate the  
behaviour, not the implementation.  Given that Apple now link CF with  
libobjc, I suspect that they are somewhat unconvinced by the benefit  
of this approach in the long run.  It's only real advantage is that it  
will work in ObjC++ code if statics are initialized with CF calls and  
these happen to run before the relevant ObjC load functions (which, I  
think, can't happen on OS X because they hacked the linker to enforce  
some stricter ordering).

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

I'd prefer you not to use objc_msg_lookup(), because it's deprecated  
in the new ABI.  There's an objc_msgSend() macro in the new runtime.h  
that generates a correct lookup-and-call sequence for either ABI.  Or  
just use Objective-C and let the compiler sort it out for you.

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


Oh yes, I forgot about that.  On OS X, NSZone is an opaque structure.  
On GNUstep, it is not, and corresponds very closely to the CFAllocator  
initializer thingy.  Of course, you could just create a new, private,  
CFAllocator class that has a single, public, NSZone ivar.

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

As Richard said, don't be afraid of modifying -base.  It might be  
necessary to modify some of the existing GNUstep classes to better  
support CF.

Stuart was also right that I oversimplified the TypeID thing.  This  
does not change with inheritance; it's the same for any all objects  
that inherit from it, and only used as the isa pointer on the (opaque)  
leaf CF classes (this allows them to function before libobjc exists,  
and to be statically initialized).  It's probably best to implement  
this with a -_cfTypeID method that returns a constant, and only  
override it in classes like NSArray, not any of their subclasses.

> Stefan
>


-- Sent from my STANTEC-ZEBRA



_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@...
http://lists.gnu.org/mailman/listinfo/gnustep-dev