[racket] Fwd: FFI: Create reference to Objective C object

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Fri Jan 2 09:49:31 EST 2015

Okay that clears up one confusion. Now for the next.

I am trying to copy this Swift code:

import Foundation
import Cocoa
import Carbon
import AppKit

// The current text input source (read keyboard) has a layout in which
// we can lookup how key-codes are resolved.

// Get the a reference keyboard using the current layout.
var unmanagedKeyboard = TISCopyCurrentKeyboardLayoutInputSource()
var keyboard = unmanagedKeyboard.takeUnretainedValue() as TISInputSource
print("Keyboard: ") ; println(keyboard)

// Get the layout
var ptrLayout   = TISGetInputSourceProperty(keyboard,
kTISPropertyUnicodeKeyLayoutData)
var layout = UnsafeMutablePointer<UCKeyboardLayout>(ptrLayout)
print("Layout: "); println(layout)


Running the code (as-is) in XCode prints:

  Keyboard: <TSMInputSource 0x10051a930> KB Layout: U.S. (id=0)
  Layout: 0x0000000102802000

In Racket I get #f (i.e. null) back as the layout.
I thought the problem was that I had defined the constant
kTISPropertyUnicodeKeyLayoutData
incorrectly, but since NSString is a reference, I think it is ok.




#lang racket
(require ffi/unsafe/objc)
(require ffi/unsafe
         ffi/unsafe/objc
         ffi/unsafe/define
         mred/private/wx/cocoa/image
         mred/private/wx/cocoa/types)

(define quartz-lib (ffi-lib
"/System/Library/Frameworks/Quartz.framework/Versions/Current/Quartz"))
(define carbon-lib (ffi-lib
"/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon"))
(define carbon-core-lib
  (ffi-lib (string-append "/System/Library/Frameworks/CoreServices.framework/"

"Frameworks/CarbonCore.framework/Versions/Current/CarbonCore")))
(define cf-lib
  (case (system-type)
    [(macosx) (ffi-lib
"/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
    [else #f]))

(define-ffi-definer define-quartz      quartz-lib)
(define-ffi-definer define-carbon-core carbon-core-lib)
(define-ffi-definer define-carbon      carbon-lib)
(define-ffi-definer define-cf          cf-lib #:default-make-fail
make-not-available)
(import-class NSString CFData)

;;; API Constants

(define _CFStringRef _NSString)
(define kTISPropertyUnicodeKeyLayoutData
  (tell (tell NSString alloc)
        initWithUTF8String: #:type _string "kTISPropertyUnicodeKeyLayoutData"))


;;; Get the current text input source (read: the keyboard)
(define _TISInputSourceRef (_cpointer 'TISInputSourceRef))
(define-carbon TISCopyCurrentKeyboardLayoutInputSource
  (_fun -> _TISInputSourceRef))

(define the-keyboard (TISCopyCurrentKeyboardLayoutInputSource))
(displayln (list 'keyboard the-keyboard))

;;; Get the layout of the keyboard
(define-cpointer-type _CFDataRef)
(define-carbon TISGetInputSourceProperty
  (_fun (_inputSource : _TISInputSourceRef)
        (_propertyKey : _CFStringRef)
        -> (_or-null _CFDataRef)))

(define the-keyboard-layout-data
  (TISGetInputSourceProperty the-keyboard "kTISPropertyUnicodeKeyLayoutData"))
(displayln (list 'layoutData the-keyboard-layout-data))


2015-01-02 14:56 GMT+01:00 Matthew Flatt <mflatt at cs.utah.edu>:
> In this example, `kTISPropertyUnicodeKeyLayoutData` is already a
> `CFStringRef` (a.k.a. `NSString*`).
>
> The type `_NSString` from `mred/private/wx/cocoa/types` (or, better for
> most purposes, from `ffi/unsafe/nsstring`) is really a pointer to an
> `_NSString`; it just gets tedious to put `Ref` or `-pointer`
> everywhere. I'll fix the docs for `_NSString`.
>
> At Fri, 2 Jan 2015 14:37:20 +0100, Jens Axel Søgaard wrote:
>> What is the best way of creating a reference to an existing Objective C object?
>>
>> Concretely given an CFString how do I get an CFStringRef  (aka pointer
>> to a CFStringRef).
>>
>> /Jens Axel
>>
>>
>> #lang racket
>> (require ffi/unsafe/objc)
>> (require ffi/unsafe
>>          ffi/unsafe/objc
>>          ffi/unsafe/define
>>          mred/private/wx/cocoa/types)
>>
>> ;; Import CoreFoundation
>> (define cf-lib
>>   (case (system-type)
>>     [(macosx) (ffi-lib
>> "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
>>     [else #f]))
>>
>> (define-ffi-definer define-cf cf-lib #:default-make-fail make-not-available)
>>
>> ;; CFString and NSString are equivalent (?)
>> (import-class NSString)
>> (define _CFString _NSString)
>>
>> ;; Create an CFString
>> (define kTISPropertyUnicodeKeyLayoutData
>>   (tell (tell NSString alloc)
>>         initWithUTF8String: #:type _string "kTISPropertyUnicodeKeyLayoutData"))
>>
>> ;; The API needs an CFStringRef that is a pointer to CFString.
>> (define _CFStringRef (_ptr i _CFString))
>>
>>
>> (define reference-to-kTISPropertyUnicodeKeyLayoutData '???)
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users



--
--
Jens Axel Søgaard


-- 
--
Jens Axel Søgaard


Posted on the users mailing list.