Search code examples
objective-cgocgo

How to get the a value of particular key out of Cocoa's NSDictionary?


package getlark

/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Cocoa
#import <Cocoa/Cocoa.h>
#import <CoreGraphics/CGWindow.h>

static NSDictionary* FindChrome(void){
        NSArray *windows = (NSArray *)CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements|kCGWindowListOptionOnScreenOnly,kCGNullWindowID);
        NSLog(@"数组长度:%lu",windows.count);
        for(NSDictionary *window in windows)
            {
                NSString *currentApp = window[(NSString *)kCGWindowOwnerName];
                NSString *currentWindowTitle = window[(NSString *)kCGWindowName];
                if ([currentApp isEqualToString:@"Google Chrome"]){
                    NSDictionary *currentBounds= window[(NSString *)kCGWindowBounds];
                    NSLog(@"%@",currentBounds);
                    return currentBounds;
                    break;
                }
            }
}
*/
import "C"
import (
    "fmt"
    "reflect"
)

func GetLarkPos() {
    var dd *C.NSDictionary

    dd = C.FindChrome()
    fmt.Println(reflect.TypeOf(dd))
    fmt.Println(dd)

}

enter image description here The value on the picture, how can I call the function of golang

Sorry, I am not familiar with cgo and objective-c. I hope I can get some help from you.


Solution

  • No, the cgo-generated getlark._Ctype_struct_NSDictionary is certainly not a Go map so dd["Height"] won't obviously work. Please note that cgo is a rather thin layer, it does not do any special magic like somehow turning random implementations of assotiative arrays done in C into Go maps.

    What you should probably do is to write helper code in your C part (that bit which defined GetChrome) which would operate on NSDictionarys. Say, something like this (completely untested):

    char *getNSDictInt(NSDictionary *dict, char *key) int {
      s_key = convertKeyToNSString(key); /* must be implemented */
      return dict[s_key];
    }
    

    and then call them like this:

    dd := C.FindChrome()
    height := C.getNSDictInt(dd, "Height")
    

    You'd need to provide such "accessors" for each type of values your NSDictionary may hold.

    (!) Note that after some digging I found out that the keys in a NSDictionary are NSStrings which are sequences of UTF-16 code units, so you must use something like this to get an *NSString out of the incoming char *key. (This can also be done on the Go side, but let's start small.)

    Another solution should be to get a ready-made package which is already prepared to deal with Cocoa API's code types–such as this or this–which both were found by a simple search.