如何从Cocoa的NSDictionary取值并通过Go的cgo获取Chrome窗口参数?
如何通过cgo从Objective-C的NSDictionary中提取Chrome窗口Bounds参数
一、Objective-C中从NSDictionary提取窗口Bounds的方法
kCGWindowBounds对应的是被NSValue包装的CGRect类型,需要先转成CGRect再提取坐标、宽高参数:
// 从窗口字典中获取Bounds值 NSValue *boundsValue = window[(NSString *)kCGWindowBounds]; // 转换为CGRect结构体 CGRect bounds = boundsValue.CGRectValue; // 提取具体参数 CGFloat x = bounds.origin.x; CGFloat y = bounds.origin.y; CGFloat width = bounds.size.width; CGFloat height = bounds.size.height;
二、修改cgo代码,让Go能直接获取可用参数
Go无法直接操作Objective-C的NSDictionary对象,因此我们在Objective-C层提前提取所需参数,通过C风格结构体返回给Go。修改后的完整代码如下:
package getlark /* #cgo CFLAGS: -x objective-c #cgo LDFLAGS: -framework Cocoa #import <Cocoa/Cocoa.h> #import <CoreGraphics/CGWindow.h> // 定义C结构体存储窗口参数,方便Go解析 typedef struct { double x; double y; double width; double height; int found; // 标记是否找到Chrome窗口 } WindowBounds; static WindowBounds FindChromeBounds(void){ WindowBounds result = {0, 0, 0, 0, 0}; NSArray *windows = (NSArray *)CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements|kCGWindowListOptionOnScreenOnly,kCGNullWindowID); for(NSDictionary *window in windows) { NSString *currentApp = window[(NSString *)kCGWindowOwnerName]; if ([currentApp isEqualToString:@"Google Chrome"]){ NSValue *boundsValue = window[(NSString *)kCGWindowBounds]; CGRect bounds = boundsValue.CGRectValue; result.x = bounds.origin.x; result.y = bounds.origin.y; result.width = bounds.size.width; result.height = bounds.size.height; result.found = 1; break; // 找到第一个Chrome窗口就终止遍历 } } CFRelease(windows); // 手动释放CGWindowListCopyWindowInfo返回的对象,避免内存泄漏 return result; } */ import "C" import "fmt" // Go侧对应的窗口参数结构体 type WindowBounds struct { X float64 Y float64 Width float64 Height float64 Found bool } func GetLarkPos() WindowBounds { cBounds := C.FindChromeBounds() return WindowBounds{ X: float64(cBounds.x), Y: float64(cBounds.y), Width: float64(cBounds.width), Height: float64(cBounds.height), Found: cBounds.found != 0, } } // 示例调用函数 func main() { bounds := GetLarkPos() if bounds.Found { fmt.Printf("Chrome窗口位置:X=%.2f, Y=%.2f,宽:%.2f,高:%.2f\n", bounds.X, bounds.Y, bounds.Width, bounds.Height) } else { fmt.Println("未找到Google Chrome窗口") } }
三、关键细节说明
- 内存管理:
CGWindowListCopyWindowInfo返回的是CF类型对象,必须用CFRelease手动释放,避免内存泄漏。 - 类型映射:C语言的
double对应Go的float64,C的int对应Go的int,通过自定义结构体可以批量传递多个参数。 - 循环优化:原代码中
return语句后不需要break(return已退出函数),修改为找到目标窗口就终止循环,减少不必要的遍历。
内容的提问来源于stack exchange,提问作者sgx
相关产品推荐
相关产品推荐

