[Pythonmac-SIG] ANN: LaunchServices 0.1 - Pythonic wrapper for the Launch Services API

Bob Ippolito bob at redivi.com
Tue Aug 26 14:33:24 EDT 2003


On Tuesday, Aug 26, 2003, at 12:24 America/New_York, Ronald Oussoren 
wrote:

>
> On Tuesday, 26 August 2003, at 15:07, Bob Ippolito wrote:
>
>> I developed a Pyrex wrapper around it, leveraging the (meager and 
>> buggy :)) CoreFoundation support that comes stock with Python 2.3.
>
> To go completely off-topic, what's wrong with the CoreFoundation 
> support in Python 2.3? That is, what bugs did you find?

Well first of all, a lot of stuff is missing (CFRunLoop, CFSocket, 
etc...), which I've ended up wrapping parts of already.  I'm guessing 
it wasn't worth the bother for CFTypeRef's that are wholly or mostly 
toll-free bridged to the Objective C side of the fence.

If would also make sense if they actually inherited CFTypeRef, so you 
could issubclass/isinstance based upon that.

It would be convenient if you could sensibly do things like 
CFStringRef('somestring') rather than _CF.toCF('somestring') and 
crossing your fingers.

I had a lot of problems with reference counting.. for example, try this:
 >>> import _CF
 >>> url = _CF.toCF('file://localhost/').CFURLCreateWithString(None)
 >>> url.CFURLGetString().toPython()
u'file://localhost/'
 >>> url.CFURLGetString().toPython()

Program received signal EXC_BAD_ACCESS, Could not access memory.
0x9068ba54 in objc_msgSend ()

 >>> import _CF
 >>> url = _CF.toCF('file://localhost/').CFURLCreateWithString(None)
 >>> url.CFURLGetString().CFRetain().toPython()
u'file://localhost/'
 >>> url.CFURLGetString().CFRetain().toPython()

Program received signal EXC_BAD_ACCESS, Could not access memory.
0x9068ba54 in objc_msgSend ()

CFRetain doesn't do anything useful at all from the Python side.  You 
never get a "nice" _CF.SomeObject out of it (you always end up with a 
CFTypeRef), and it doesn't increase the retain count in a useful way 
(the retain count does go up -- but only so long as you hold on to the 
new object.. it's just giving you two python references to the same 
thing each with their own reference to the CFTypeRef, when both go away 
so does the CFTypeRef).  I ended up doing this in Pyrex as a workaround 
for now:

def CFRetainForReal(obj):
     cdef CFTypeRef tref
     CFObj_Convert(obj, &tref)
     CFRetain(tref)
     return obj

I only had to use it in one function (I'll include the relevant others 
for context).. I could just be lucky, I haven't gone through it with a 
hammer and a fine toothed comb to check for leaks.

def CFStringFromObject(obj):
     """
     CFStringFromObject(obj) -> _CF.CFStringRef
     """
     if isinstance(obj, _CF.CFStringRef):
         return obj
     if isinstance(obj, _CF.CFURLRef):
         # XXX - this one seems ok w/o the retain hack
         url = obj.CFURLCopyAbsoluteURL()
         return url.CFURLGetString()
     # cross fingers and hope a CFStringRef pops out
     cfString = _CF.toCF(obj)
     if not isinstance(cfString, _CF.CFStringRef):
         raise ValueError, 'Must be a string'
     return cfString

def CFURLFromObject(obj, base=None):
     """
     CFURLFromObject(obj, base=None) -> _CF.CFURLRef
     """
     cdef CFStringRef _cfString
     cdef CFURLRef _cfURL
     cdef CFURLRef _cfURLbase
     if isinstance(obj, _CF.CFURLRef):
         return obj
     cfString = CFStringFromObject(obj)
     CFStringRefObj_Convert(cfString, &_cfString)
     if base is None:
         _cfURLbase = NULL
     else:
         CFURLRefObj_Convert(CFURLFromObject(base), &_cfURLbase)
     _cfURL = CFURLCreateWithString(kCFAllocatorDefault, _cfString, 
_cfURLbase)
     if (_cfURL == NULL):
         raise ValueError, 'Not a valid URL'
     return CFObj_New(CFRetain(_cfURL))


def PathToURL(path):
     """
     PathToURL(path) -> unicode_url
     """
     path = CFStringFromObject(path).toPython().encode('utf8')
     # XXX - this is where the bug shows up
     cfurl = CFRetainForReal(_CF.CFURLCreateFromFSRef(path))
     cfstr = CFStringFromObject(cfurl)
     return cfstr.toPython()




More information about the Pythonmac-SIG mailing list