Files
2022-12-10 02:18:03 -07:00

265 lines
7.2 KiB
Go

//go:build darwin && cgo && objc
package objc
/*
// #cgo CFLAGS: -Dqqq
// #cgo LDFLAGS: -lobjc -framework Foundation
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <dlfcn.h>
#include <objc/objc-runtime.h>
static int objcBOOL2int(BOOL b) {
return (int)b;
}
*/
import "C"
import (
"unsafe"
)
type Class uintptr
func GetClass(name string) Class {
return (Class)(unsafe.Pointer(C.objc_getClass(C.CString(name))))
}
func ClassList() (classes []Class) {
var outCount C.uint
var classPointers []C.Class
p := (C.objc_copyClassList(&outCount))
result := make([]Class, outCount)
if p != nil {
classPointers = (*[1 << 30]C.Class)(unsafe.Pointer(p))[0:outCount]
for i := 0; i < int(outCount); i++ {
result[i] = (Class)(unsafe.Pointer(classPointers[i]))
}
C.free(unsafe.Pointer(p))
}
return result
}
func GetMetaClass(name string) Class {
return (Class)(unsafe.Pointer(C.objc_getMetaClass(C.CString(name))))
}
func (cls Class) cclass() C.Class {
return (C.Class)(unsafe.Pointer(cls))
}
func (cls Class) cid() C.id {
return (C.id)(unsafe.Pointer(cls))
}
func (cls Class) Name() string {
return C.GoString(C.class_getName(cls.cclass()))
}
func (cls Class) Super() Class {
return (Class)(unsafe.Pointer(C.class_getSuperclass(cls.cclass())))
}
func (cls Class) IsMetaClass() bool {
return C.objcBOOL2int(C.class_isMetaClass(cls.cclass())) != 0
}
func (cls Class) InstanceSize() int {
return int(C.class_getInstanceSize(cls.cclass()))
}
func (cls Class) ClassVariable(name string) Ivar {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
return (Ivar)(unsafe.Pointer(C.class_getClassVariable(cls.cclass(), cname)))
}
// func (cls Class) AddIvar(name string, size uint, alignment uint8, types string) bool {
// cname := C.CString(name)
// defer C.free(unsafe.Pointer(cname))
// ctypes := C.CString(types)
// defer C.free(unsafe.Pointer(ctypes))
// return C.class_addIvar(cls.cclass(), cname, C.size_t(size), C.uint8_t(alignment), ctypes) != 0
// }
func (cls Class) Ivar(name string) Ivar {
return (Ivar)(unsafe.Pointer(C.class_getInstanceVariable(cls.cclass(), C.CString(name))))
}
func (cls Class) Ivars() []Ivar {
var outCount C.uint
var ivarPointers []C.Ivar
p := (C.class_copyIvarList(cls.cclass(), &outCount))
result := make([]Ivar, outCount)
if p != nil {
ivarPointers = (*[1 << 30]C.Ivar)(unsafe.Pointer(p))[0:outCount]
for i := 0; i < int(outCount); i++ {
result[i] = (Ivar)(unsafe.Pointer(ivarPointers[i]))
}
C.free(unsafe.Pointer(p))
}
return result
}
func (cls Class) Method(name string) Method {
sel := C.sel_registerName(C.CString(name))
return (Method)(unsafe.Pointer(C.class_getClassMethod(cls.cclass(), sel)))
}
func (cls Class) InstanceMethod(name Sel) Method {
return (Method)(unsafe.Pointer(C.class_getInstanceMethod(cls.cclass(), name.csel())))
}
func (cls Class) GetMethodImplementation(name Sel) C.IMP {
return C.IMP(C.class_getMethodImplementation(cls.cclass(), name.csel()))
}
func (cls Class) RespondsToSelector(sel Sel) bool {
return C.objcBOOL2int(C.class_respondsToSelector(cls.cclass(), sel.csel())) != 0
}
func (cls Class) Methods() []Method {
var outCount C.uint
var methodPointers []C.Method
p := (C.class_copyMethodList(cls.cclass(), &outCount))
result := make([]Method, outCount)
if p != nil {
methodPointers = (*[1 << 30]C.Method)(unsafe.Pointer(p))[0:outCount]
for i := 0; i < int(outCount); i++ {
result[i] = (Method)(unsafe.Pointer(methodPointers[i]))
}
C.free(unsafe.Pointer(p))
}
return result
}
func (cls Class) Property(name string) Property {
return (Property)(unsafe.Pointer(C.class_getProperty(cls.cclass(), C.CString(name))))
}
func (cls Class) Properties() []Property {
var outCount C.uint
var properties []C.objc_property_t
p := (C.class_copyPropertyList(cls.cclass(), &outCount))
result := make([]Property, outCount)
if p != nil {
properties = (*[1 << 30]C.objc_property_t)(unsafe.Pointer(p))[0:outCount]
for i := 0; i < int(outCount); i++ {
result[i] = (Property)(unsafe.Pointer(properties[i]))
}
C.free(unsafe.Pointer(p))
}
return result
}
// func (cls Class) AddMethod(name Sel, imp Imp, types string) bool {
// ctype := C.CString(types)
// defer C.free(unsafe.Pointer(ctype))
// return C.class_addMethod(cls, name, imp, ctype) != 0
// }
// func (cls Class) ReplaceMethod(name Sel, imp Imp, types string) Imp {
// ctype := C.CString(types)
// defer C.free(unsafe.Pointer(ctype))
// return Imp(C.class_replaceMethod(cls, name, imp, ctype))
// }
// func (cls Class) AddProtocol(protocol Protocol) bool {
// return C.class_addProtocol(cls, protocol) != 0
// }
// func (cls Class) AddProperty(name string, attributes []PropertyAttribute) bool {
// var cattributes *C.objc_property_attribute_t
// cname := C.CString(name)
// defer C.free(unsafe.Pointer(cname))
// attrSize := unsafe.Sizeof(*cattributes)
// attributeCount := len(attributes)
// if len(attributes) != 0 {
// cattributes = (*C.objc_property_attribute_t)(calloc(uint(attributeCount), attrSize))
// defer func(cattributes *C.objc_property_attribute_t, attributeCount int) {
// for i, elem := 0, cattributes; i < attributeCount; i++ {
// C.free(unsafe.Pointer(elem.name))
// C.free(unsafe.Pointer(elem.value))
// elem = nextPropertyAttr(elem)
// }
// C.free(unsafe.Pointer(cattributes))
// }(cattributes, attributeCount)
// for i, elem := 0, cattributes; i < attributeCount; i++ {
// attr := attributes[i]
// elem.name = C.CString(attr.Name)
// elem.value = C.CString(attr.Value)
// elem = nextPropertyAttr(elem)
// }
// }
// return C.class_addProperty(cls, cname, cattributes, C.uint(attributeCount)) != 0
// }
// func (cls Class) ReplaceProperty(name string, attributes []PropertyAttribute) {
// var cattributes *C.objc_property_attribute_t
// cname := C.CString(name)
// defer C.free(unsafe.Pointer(cname))
// attrSize := unsafe.Sizeof(*cattributes)
// attributeCount := len(attributes)
// if len(attributes) != 0 {
// cattributes = (*C.objc_property_attribute_t)(calloc(uint(attributeCount), attrSize))
// defer func(cattributes *C.objc_property_attribute_t, attributeCount int) {
// for i, elem := 0, cattributes; i < attributeCount; i++ {
// C.free(unsafe.Pointer(elem.name))
// C.free(unsafe.Pointer(elem.value))
// elem = nextPropertyAttr(elem)
// }
// C.free(unsafe.Pointer(cattributes))
// }(cattributes, attributeCount)
// for i, elem := 0, cattributes; i < attributeCount; i++ {
// attr := attributes[i]
// elem.name = C.CString(attr.Name)
// elem.value = C.CString(attr.Value)
// elem = nextPropertyAttr(elem)
// }
// }
// C.class_replaceProperty(cls, cname, cattributes, C.uint(attributeCount))
// }
func (cls Class) ConformsToProtocol(prot Protocol) bool {
return C.objcBOOL2int(C.class_conformsToProtocol(cls.cclass(), prot.cprot())) != 0
}
func (cls Class) Version() int {
return int(C.class_getVersion(cls.cclass()))
}
func (cls Class) SetVersion(version int) {
C.class_setVersion(cls.cclass(), C.int(version))
}
func (cls Class) CreateInstance(extraBytes uint) Id {
return (Id)(unsafe.Pointer(C.class_createInstance(cls.cclass(), C.size_t(extraBytes))))
}
func (cls Class) GetImageName() string {
return C.GoString(C.class_getImageName(cls.cclass()))
}