[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