Converting CFDictionaryRef to NSDictionary

So a while ago (Hopefully shane can remember this without drinking), I was trying to work with KextManagerCopyLoadedKextInfo(), and it wasn’t working in ASOC because ASOC couldn’t deal with CFDictionaryRefs at all.

If you even tried it, you got errors and no results at all, usable or not. Even with his help on the ObjC side, the data I got back wasn’t terribly parseable.

But that was back in 2015, and it looks like things have changed a little.

Now, if I try: set theResultDict to current application’s KextManagerCopyLoadedKextInfo(missing value, missing value), I don’t get an error, (yay!) I get a pointer, which is what I expected:

«class cptr» id «data gptr00000000800B0D02006000007B5F5F434644696374696F6E6172793D7D00»

So now the question is, since I’m assuming that’s a “real” pointer, is there any (relatively) easy way to get that data and shove it into an NSDIctionary.

The docs I can find on moving from CFDictionaryRef to NSDictionary are not exactly clear (enough for my wee brain yet), but what I can derive from them seems straightforward? It’s dealing with the pointers that make things…interesting.

any tips/ideas?

CFDictionaryRef pointers should be “toll-free” bridged to NSDictionary pointers, meaning that you can use the pointer in either context without any conversion.

Although they can be bridged as Mark describes, I’ve yet to see a way to do it.

The value returned is just an generic C pointer to an object whose class is BAImmediateData and not an CFDictionaryRef as you expect.

use AppleScript version "2.7" -- Code works only on High Sierra (but works on old AS version on HS)
use framework "Foundation"
use framework "CoreFoundation"
use framework "IOKit"

set theResultDict to current application's KextManagerCopyLoadedKextInfo(missing value, missing value)
set classOftheResultDict to current application's NSStringFromClass(theResultDict's |class|())
return classOftheResultDict as string

If the pointer was pointing to an CFDictionaryRef then you could indeed use NSDictionary’s initWithDictionary:copyItems: to create an NSDictionary from an CFDictionaryRef. However it wouldn’t be necessary because they’re toll-free which means NSDictionary methods can handle CFDictionaryRef opaque types.

Update: When using CFDictionaryCreateCopy() from CoreFoundation I get an BAImmediateData type back from AppleScriptObjC as well. I was expecting at least BAGenericObject class which still allows you to send messages using AppleScriptObjC. So my conclusion is that AppleScriptObjC is handling CFDictionaryRef just as an generic C pointer, which can be anything.

While you may seem like you have found a C pointer, you’re miles away at the same time because the address in «class cptr» is from another memory space and can’t be coerced into an «class ocid» that easy.

DJ,

I wasn’t trying to make assumptions on the kind of pointer, just that it looked like one :slight_smile:

But yeah, if I try initWithDictionary:copyItems, it consistently fails with unrecognized selector. Sigh. So close, and yet so far.

I did however file a bug on this with Apple. Beats doing nothing.