============================
API Notes for CoreFoundation
============================

Introduction
------------

This document describes where the wrappers for CoreFoundation API are different
from the default straightforward translation of method/function interfaces.

Containers
----------

Container datastructures, such as ``CFArray`` and ``CFTree``, are only 
supported when the contain only ``CFTypeRef`` values even when the actual
C API supports arbitrary pointer values.

Toll-free bridging
------------------

Toll-free bridging applies to Python as well, and is more convenient than
in Objective-C because you don't have to cast between a CoreFoundation type
and an Objective-C class.




CFArrayRef
----------

This type is only supported when the ``callbacks`` are 
``kCFTypeArrayCallBacks``, accessing other ``CFArray`` values from Python is 
not supported and will crash your interpreter.

Note that all ``CFArrayRef`` instances are instances of ``NSArray`` or
``NSMutableArray`` as well.  


* ``CFArrayCreate``, ``CFArrayCreateMutable``

  The ``callbacks`` argument must be ``kCFTypeArrayCallbacks``.

* The ``context`` argument for ``CFArrayApplyFunction``, 
  ``CFArrayBSearchValues`` and ``CFArraySortValues``  can be an arbitrary
  object (unlike the ``context`` or ``userdata`` argument in a lot of other
  API's).


CFBagRef
--------

This type is only supported when the ``callbacks`` are 
``kCFTypeBagCallBacks``, accessing other ``CFBag`` values from Python is not
supported.

* ``CFBagCreate``, ``CFBagCreateMutable``

  These function don't have a ``callBacks`` argument in Python and will always 
  use the ``kCFTypeBagCallBacks`` value for that argument in C.

* The ``context`` argument for ``CFBagApplyFunction`` can be an arbitrary
  Python object.

CFBinaryHeapRef
---------------

The ``CFBinaryHeap`` wrappers assume that values are instances of CoreFoundation
types or Objective-C classes.

* ``CFBinaryHeapCreate``

  The ``callbacks`` argument is not present in Python and is automaticly
  set to a value that allows arbitrary objects that implement the 
  ``compare:`` method.

  The ``compareContext`` argument is also not present in Python.

* ``CFBinaryHeapGetMinimumIfPresent``

  This function is useless in Python, the bridge assumes that the ``value``
  is always a valid pointer.

CFBundle
--------

* ``CFBundleGetFunctionPointerForName``, 
  ``CFBundleGetFunctionPointersForNames``,
  ``CFBundleGetDataPointerForName`` and
  ``CFBundleGetDataPointersForNames``: these functions are not supported,
  use the native PyObjC bundle loading API's instead (the the core
  PyObjC documentation for details).

CFData
------

* ``CFDataGetBytePtr``, ``CFDataGetMutableBytePtr``: these functions return
  an ``objc.varlist`` of bytes. A varlist doesn't implement the buffer 
  interface, but can be used to peek into the buffer (and poke bytes into
  the buffer when you're using ``CFDataGetMutableBytePtr``).

CFDictionary
------------

* ``CFDictionaryCreate``, ``CFDictionaryCreateMutable``: the callback
  arguments are must be ``kCFTypeDictionaryKeyCallBacks`` and
  ``kCFTypeDictionaryValueCallBacks``.

  instances contain objects (both as keys and as values)

* ``CFDictionaryApplyFunction``: the ``context`` argument can be an
  arbitrary Python object.

CFFileDescriptor
----------------

* The ``context`` argument for ``CFFileDescriptorCreate`` is a python object,
  the ``CFFileDescriptorContext`` is automaticly added by the bridge.

* The ``CFFileDescriptorGetContext`` results the python object that was
  used in ``CFFileDescriptorContext``, not a ``CFFileDescriptorContext``
  structure.

  NOTE: This means it is unsafe to call ``CFFileDescriptorGetContext`` on
  objects that weren't created in Python code.

CFMachPort
----------

NOTE: the current bindings for the CFMachPort API are probably useless, as 
there doesn't seem to be a proper binding of the low-level API's.

* The ``context`` argument for ``CFMachPortCreate``  and 
  ``CFMachPortCreateWithPort`` is a python object, the 
  ``CFMachPortContext`` is automaticly added by the bridge.

* The ``CFMachPortGetContext`` results the python object that was
  used in ``CFMachPortContext``, not a ``CFMachPortContext``
  structure.
  
  NOTE: This means it is unsafe to call ``CFMachPortContext`` on
  objects that weren't created in Python code.

CFNumber
--------

Note that Python numbers are automaticly translated to/from Objective-C
numbers (NSNumber, which toll-free bridged to CFNumber). This means the
CFNumber functions should almost never be necessary.

That said, all CFNumber API's do actually work.

CFNumberFormatter
-----------------

* ``CFNumberFormatterCreateStringWithValue``: this function is not 
  supported at the moment, use ``CFNumberFormatterCreateStringWithNumber``
  instead.

* ``CFNumberFormatterGetValueFromString``: this function is not
  supported at the moment, use ``CFNumberFormatterCreateNumberFromString``
  instead.

NOTE: Both function require a manual wrapper to support, implementations are
welcome.

CFPlugin
--------

The ``CFPlugin`` API's are not supported at the moment. Likewise for the 
COM interface support in CoreFoundation.

CFRunLoopSource
---------------

The 'context' argument for ``CFRunLoopSourceCreate`` should be a tuple. The first
element of the tuple is ``0``, the other elements are: a ``schedule`` callback,
a ``cancel`` callback, a ``perform`` callback and an ``info`` object. The callbacks
may be ``None``.

Version 1 of the context object is not yet supported.

The ``CFRunLoopSourceGetContext`` returns this tuple, and will raise an exception
when the context was not set from Python (that is, when asking for the context of
a runloop source that was created in C code).

CFRunLoopTimer
--------------

The ``context`` argument of ``CFRunLoopTimerCreate`` can be an arbitrary python
object. This object is returned by ``CFRunLoopTimerGetContext``.

CFRunLoopObserver
-----------------

The ``context`` argument of ``CFRunLoopObserverCreate`` can be an arbitrary python
object. This object is returned by ``CFRunLoopObserverGetContext``.


CFSet
-----

* ``CFSetCreate``, ``CFSetCreateMutable``: the ``callbacks`` argument is
  a magic argument in Python, not a collection of function pointers. It
  must be ``kCFTypeSetCallbacks``.

* ``CFSetApplyFunction``: The ``context`` argument can be an arbitrary object.

CFSocket
--------

The socket context is an arbitrary object, not a callback structure. This has
several effects:

* Do not try to access the context of sockets that aren't created in Python

* The ``context`` argument for ``CFSocketCreate``, ``CFSocketCreateWithNative``,
  ``CFSocketCreateWithSocketSignature``, 
  ``CFSocketCreateConnectedToSocketSignature`` is an arbitrary python object.

* The function ``CFSocketGetContext`` returns that python object and will crash
  when the context was not set from Python.


CFStream
--------

* You can use any Python object as the client context for ``CFReadStreamSetClient`` 
  and ``CFWriteStreamSetClient``. Use ``objc.NULL`` to remove a client.

CFString
--------

* The 'Pascal String' API's are not supported (that is,
  ``CFStringAppendPascalString``, ``CFStringCreateWithPascalString``,
  ``CFStringCreateWithPascalStringNoCopy``, ``CFStringGetPascalString``, and
  ``CFStringGetPascalStringPtr``). 
  Use the regular Python string API's instead (or access the string 
  contents using the ``CString`` functions, use as 
  ``CFStringCreateWithCString``).


CFTree
------

* The ``context`` attribute (that is ``context`` argument for
  ``CFTreeCreate`` and ``CFTreeGetContext``) can be an arbitrary python
  object, it is not a ``CFTreeContext`` structure as in C.

CFXMLParser, CFXMLNode
----------------------

* These API's are not supported for now. The ``Create`` functions need
  manual wrappers, which haven't been written yet. There are also no
  uninttests for the automaticly created bindings.

* Use a Python XML parser (such as ElementTree) instead.
