objc: add protocol support (#46)
needed for ebitengien#2326
- commit
- aa1b0f680473761735af9ba5c3c0ee717fdb39db
- author
- TotallyGamerJet · · 2022-09-15 04:40 UTC
- committer
- GitHub · · 2022-09-15 04:40 UTC
- parent
- 02d7b30
- signature
- GPG Unverified
4AEE18F83AFDEB23The key is unknown
1 file · +22 -0
M objc/objc_runtime_darwin.go +22 -0
| @@ -25,6 +25,7 @@ var ( | |||
| 25 | 25 | objc_msgSend = purego.Dlsym(objc, "objc_msgSend") | |
| 26 | 26 | objc_msgSendSuper2 = purego.Dlsym(objc, "objc_msgSendSuper2") | |
| 27 | 27 | objc_getClass = purego.Dlsym(objc, "objc_getClass") | |
| 28 | + | objc_getProtocol = purego.Dlsym(objc, "objc_getProtocol") | |
| 28 | 29 | objc_allocateClassPair = purego.Dlsym(objc, "objc_allocateClassPair") | |
| 29 | 30 | objc_registerClassPair = purego.Dlsym(objc, "objc_registerClassPair") | |
| 30 | 31 | sel_registerName = purego.Dlsym(objc, "sel_registerName") | |
| @@ -32,6 +33,7 @@ var ( | |||
| 32 | 33 | class_getInstanceVariable = purego.Dlsym(objc, "class_getInstanceVariable") | |
| 33 | 34 | class_addMethod = purego.Dlsym(objc, "class_addMethod") | |
| 34 | 35 | class_addIvar = purego.Dlsym(objc, "class_addIvar") | |
| 36 | + | class_addProtocol = purego.Dlsym(objc, "class_addProtocol") | |
| 35 | 37 | ivar_getOffset = purego.Dlsym(objc, "ivar_getOffset") | |
| 36 | 38 | object_getClass = purego.Dlsym(objc, "object_getClass") | |
| 37 | 39 | ) | |
| @@ -189,6 +191,14 @@ func (c Class) AddIvar(name string, ty interface{}, types string) bool { | |||
| 189 | 191 | return byte(ret) != 0 | |
| 190 | 192 | } | |
| 191 | 193 | ||
| 194 | + | // AddProtocol adds a protocol to a class. | |
| 195 | + | // Returns true if the protocol was added successfully, otherwise false (for example, | |
| 196 | + | // the class already conforms to that protocol). | |
| 197 | + | func (c Class) AddProtocol(protocol *Protocol) bool { | |
| 198 | + | ret, _, _ := purego.SyscallN(class_addProtocol, uintptr(c), uintptr(unsafe.Pointer(protocol))) | |
| 199 | + | return byte(ret) != 0 | |
| 200 | + | } | |
| 201 | + | ||
| 192 | 202 | // InstanceVariable returns an Ivar data structure containing information about the instance variable specified by name. | |
| 193 | 203 | func (c Class) InstanceVariable(name string) Ivar { | |
| 194 | 204 | n := strings.CString(name) | |
| @@ -215,6 +225,18 @@ func (i Ivar) Offset() uintptr { | |||
| 215 | 225 | return ret | |
| 216 | 226 | } | |
| 217 | 227 | ||
| 228 | + | // Protocol is a type that declares methods that can be implemented by any class. | |
| 229 | + | type Protocol uintptr | |
| 230 | + | ||
| 231 | + | // GetProtocol returns the protocol for the given name or nil if there is no protocol by that name. | |
| 232 | + | func GetProtocol(name string) *Protocol { | |
| 233 | + | n := strings.CString(name) | |
| 234 | + | p, _, _ := purego.SyscallN(objc_getProtocol, uintptr(unsafe.Pointer(n))) | |
| 235 | + | runtime.KeepAlive(n) | |
| 236 | + | // We take the address and then dereference it to trick go vet from creating a possible miss-use of unsafe.Pointer | |
| 237 | + | return *(**Protocol)(unsafe.Pointer(&p)) | |
| 238 | + | } | |
| 239 | + | ||
| 218 | 240 | // IMP is a function pointer that can be called by Objective-C code. | |
| 219 | 241 | type IMP uintptr | |
| 220 | 242 | ||
| @@ -25,6 +25,7 @@ var ( | |||||
| 25 | objc_msgSend = purego.Dlsym(objc, "objc_msgSend") | 25 | objc_msgSend = purego.Dlsym(objc, "objc_msgSend") | ||
| 26 | objc_msgSendSuper2 = purego.Dlsym(objc, "objc_msgSendSuper2") | 26 | objc_msgSendSuper2 = purego.Dlsym(objc, "objc_msgSendSuper2") | ||
| 27 | objc_getClass = purego.Dlsym(objc, "objc_getClass") | 27 | objc_getClass = purego.Dlsym(objc, "objc_getClass") | ||
| 28 | + | objc_getProtocol = purego.Dlsym(objc, "objc_getProtocol") | |||
| 28 | objc_allocateClassPair = purego.Dlsym(objc, "objc_allocateClassPair") | 29 | objc_allocateClassPair = purego.Dlsym(objc, "objc_allocateClassPair") | ||
| 29 | objc_registerClassPair = purego.Dlsym(objc, "objc_registerClassPair") | 30 | objc_registerClassPair = purego.Dlsym(objc, "objc_registerClassPair") | ||
| 30 | sel_registerName = purego.Dlsym(objc, "sel_registerName") | 31 | sel_registerName = purego.Dlsym(objc, "sel_registerName") | ||
| @@ -32,6 +33,7 @@ var ( | |||||
| 32 | class_getInstanceVariable = purego.Dlsym(objc, "class_getInstanceVariable") | 33 | class_getInstanceVariable = purego.Dlsym(objc, "class_getInstanceVariable") | ||
| 33 | class_addMethod = purego.Dlsym(objc, "class_addMethod") | 34 | class_addMethod = purego.Dlsym(objc, "class_addMethod") | ||
| 34 | class_addIvar = purego.Dlsym(objc, "class_addIvar") | 35 | class_addIvar = purego.Dlsym(objc, "class_addIvar") | ||
| 36 | + | class_addProtocol = purego.Dlsym(objc, "class_addProtocol") | |||
| 35 | ivar_getOffset = purego.Dlsym(objc, "ivar_getOffset") | 37 | ivar_getOffset = purego.Dlsym(objc, "ivar_getOffset") | ||
| 36 | object_getClass = purego.Dlsym(objc, "object_getClass") | 38 | object_getClass = purego.Dlsym(objc, "object_getClass") | ||
| 37 | ) | 39 | ) | ||
| @@ -189,6 +191,14 @@ func (c Class) AddIvar(name string, ty interface{}, types string) bool { | |||||
| 189 | return byte(ret) != 0 | 191 | return byte(ret) != 0 | ||
| 190 | } | 192 | } | ||
| 191 | 193 | ||||
| 194 | + | // AddProtocol adds a protocol to a class. | |||
| 195 | + | // Returns true if the protocol was added successfully, otherwise false (for example, | |||
| 196 | + | // the class already conforms to that protocol). | |||
| 197 | + | func (c Class) AddProtocol(protocol *Protocol) bool { | |||
| 198 | + | ret, _, _ := purego.SyscallN(class_addProtocol, uintptr(c), uintptr(unsafe.Pointer(protocol))) | |||
| 199 | + | return byte(ret) != 0 | |||
| 200 | + | } | |||
| 201 | + | ||||
| 192 | // InstanceVariable returns an Ivar data structure containing information about the instance variable specified by name. | 202 | // InstanceVariable returns an Ivar data structure containing information about the instance variable specified by name. | ||
| 193 | func (c Class) InstanceVariable(name string) Ivar { | 203 | func (c Class) InstanceVariable(name string) Ivar { | ||
| 194 | n := strings.CString(name) | 204 | n := strings.CString(name) | ||
| @@ -215,6 +225,18 @@ func (i Ivar) Offset() uintptr { | |||||
| 215 | return ret | 225 | return ret | ||
| 216 | } | 226 | } | ||
| 217 | 227 | ||||
| 228 | + | // Protocol is a type that declares methods that can be implemented by any class. | |||
| 229 | + | type Protocol uintptr | |||
| 230 | + | ||||
| 231 | + | // GetProtocol returns the protocol for the given name or nil if there is no protocol by that name. | |||
| 232 | + | func GetProtocol(name string) *Protocol { | |||
| 233 | + | n := strings.CString(name) | |||
| 234 | + | p, _, _ := purego.SyscallN(objc_getProtocol, uintptr(unsafe.Pointer(n))) | |||
| 235 | + | runtime.KeepAlive(n) | |||
| 236 | + | // We take the address and then dereference it to trick go vet from creating a possible miss-use of unsafe.Pointer | |||
| 237 | + | return *(**Protocol)(unsafe.Pointer(&p)) | |||
| 238 | + | } | |||
| 239 | + | ||||
| 218 | // IMP is a function pointer that can be called by Objective-C code. | 240 | // IMP is a function pointer that can be called by Objective-C code. | ||
| 219 | type IMP uintptr | 241 | type IMP uintptr | ||
| 220 | 242 | ||||