rubicon.objc.runtime - Low-level Objective-C runtime access¶
This module contains types, functions, and C libraries used for low-level access to the Objective-C runtime.
In most cases there is no need to use this module directly — the rubicon.objc.api module provides the same functionality through a high-level interface.
C libraries¶
Some commonly used C libraries are provided as CDLLs. Other libraries can be loaded using the load_library function.
rubicon.objc.runtime.load_library
¶
load_library(name)
Load and return the C library with the given name.
If the library could not be found, a ValueError is raised.
Internally, this function uses ctypes.util.find_library to search for the
library in the system-standard locations. If the library cannot be found this way,
it is attempted to load the library from certain hard-coded locations, as a fallback
for systems where find_library does not work (such as iOS).
rubicon.objc.runtime.libc
module-attribute
¶
libc = load_library('c')
rubicon.objc.runtime.libobjc
module-attribute
¶
libobjc = load_library('objc')
The Objective-C runtime library.
The following functions are accessible by default:
class_addIvarclass_addMethodclass_addPropertyclass_addProtocolclass_copyIvarListclass_copyMethodListclass_copyPropertyListclass_copyProtocolListclass_getClassMethodclass_getClassVariableclass_getInstanceMethodclass_getInstanceSizeclass_getInstanceVariableclass_getIvarLayoutclass_getMethodImplementationclass_getNameclass_getPropertyclass_getSuperclassclass_getVersionclass_getWeakIvarLayoutclass_isMetaClassclass_replaceMethodclass_respondsToSelectorclass_setIvarLayoutclass_setVersionclass_setWeakIvarLayoutivar_getNameivar_getOffsetivar_getTypeEncodingmethod_exchangeImplementationsmethod_getImplementationmethod_getNamemethod_getTypeEncodingmethod_setImplementationobjc_allocateClassPairobjc_copyProtocolListobjc_getAssociatedObjectobjc_getClassobjc_getMetaClassobjc_getProtocolobjc_registerClassPairobjc_removeAssociatedObjectsobjc_setAssociatedObjectobject_getClassobject_getClassNameobject_getIvarobject_setIvarproperty_getAttributesproperty_getNameproperty_copyAttributeListprotocol_addMethodDescriptionprotocol_addProtocolprotocol_addPropertyobjc_allocateProtocolprotocol_conformsToProtocolprotocol_copyMethodDescriptionListprotocol_copyPropertyListprotocol_copyProtocolListprotocol_getMethodDescriptionprotocol_getNameobjc_registerProtocolsel_getNamesel_isEqualsel_registerName
rubicon.objc.runtime.Foundation
module-attribute
¶
Foundation = load_library('Foundation')
The Foundation framework.
Objective-C runtime types¶
These are various types used by the Objective-C runtime functions.
rubicon.objc.runtime.objc_block
¶
Bases: objc_id
The low-level type of block pointers.
This type tells Rubicon's internals that the object in question is a block and not just a regular Objective-C object, which affects method argument and return value conversions. For more details, see Objective-C Blocks.
Note
This type does not correspond to an actual C type or Objective-C class. Although the internal structure of block objects is documented, as well as the fact that they are Objective-C objects, they do not have a documented type or class name and are not fully defined in any header file.
Aside from the special conversion behavior, this type is equivalent to
objc_id.
rubicon.objc.runtime.SEL
¶
SEL(init=None)
rubicon.objc.runtime.IMP
¶
rubicon.objc.runtime.objc_property_t
¶
Bases: c_void_p
The objc_property_t
type from <objc/runtime.h>.
rubicon.objc.runtime.objc_property_attribute_t
¶
rubicon.objc.runtime.objc_method_description
¶
rubicon.objc.runtime.objc_super
¶
Objective-C runtime utility functions¶
These utility functions provide easier access from Python to certain parts of the Objective-C runtime.
rubicon.objc.runtime.object_isClass
¶
object_isClass(obj)
Return whether the given Objective-C object is a class (or a metaclass).
This is equivalent to the libobjc function
object_isClass
from <objc/runtime.h>, which is only available since OS X 10.10 and
iOS 8. This module-level function is provided to support older systems
— it uses the libobjc function if
available, and otherwise emulates it.
rubicon.objc.runtime.get_class
¶
get_class(name)
Get the Objective-C class with the given name as a
Class object.
If no class with the given name is loaded, None is returned, and the Objective-C
runtime will log a warning message.
rubicon.objc.runtime.should_use_stret
¶
should_use_stret(restype)
Return whether a method returning the given type must be called using
objc_msgSend_stret on the current system.
rubicon.objc.runtime.should_use_fpret
¶
should_use_fpret(restype)
Return whether a method returning the given type must be called using
objc_msgSend_fpret on the current system.
rubicon.objc.runtime.send_message
¶
send_message(receiver, selector, *args, restype, argtypes=None, varargs=None)
Call a method on the receiver with the given selector and arguments.
This is the equivalent of an Objective-C method call like [receiver sel:args].
Note
Some Objective-C methods take variadic arguments (varargs), for example
+[NSString stringWithFormat:] <https://developer.apple.com/documentation/foundation/nsstring/stringwithformat:?language=objc>_.
When using :func:send_message, variadic arguments are treated
differently from regular arguments: they are not passed as normal
function arguments in *args, but as a list in a separate varargs
keyword argument.
This explicit separation of regular and variadic arguments protects
against accidentally passing too many arguments into a method. By
default these extra arguments would be considered varargs and passed on
to the method, even if the method in question doesn't take varargs.
Because of how the Objective-C runtime and most C calling conventions
work, this error would otherwise be silently ignored.
The types of varargs are not included in the argtypes list. Instead,
the values are automatically converted to C types using the default
ctypes argument conversion rules. To ensure that all varargs are
converted to the expected C types, it is recommended to manually convert
all varargs to ctypes types instead of relying on automatic
conversions. For example:
send_message(
NSString,
"stringWithFormat:",
at("%i %s %@"),
restype=objc_id,
argtypes=[objc_id],
varargs=[c_int(123), cast(b"C string", c_char_p), at("ObjC string")],
)
| PARAMETER | DESCRIPTION |
|---|---|
receiver
|
The object on which to call the method, as an
|
selector
|
|
args
|
The method arguments.
DEFAULT:
|
restype
|
The return type of the method.
|
argtypes
|
The argument types of the method, as a
DEFAULT:
|
varargs
|
Variadic arguments for the method, as a
DEFAULT:
|
rubicon.objc.runtime.send_super
¶
send_super(
cls,
receiver,
selector,
*args,
restype=c_void_p,
argtypes=None,
varargs=None,
_allow_dealloc=False,
)
In the context of the given class, call a superclass method on the receiver with the given selector and arguments.
This is the equivalent of an Objective-C method call like
[super sel:args] in the class cls.
In practice, the first parameter should always be the special variable
__class__, and the second parameter should be self. A typical
send_super call would be
send_super(__class__, self, 'init') for example.
The special variable __class__ is defined by Python and stands for the
class object that is being created by the current class block. The
exact reasons why __class__ must be passed manually are somewhat
technical, and are not directly relevant to users of
send_super.
For a full explanation, see issue
beeware/rubicon-objc#107 and
PR beeware/rubicon-objc#108.
Although it is possible to pass other values than __class__ and
self for the first two parameters, this is strongly discouraged. Doing
so is not supported by the Objective-C language, and relies on
implementation details of the superclasses.
| PARAMETER | DESCRIPTION |
|---|---|
cls
|
|
receiver
|
The object on which to call the method, as an
|
selector
|
|
args
|
The method arguments.
DEFAULT:
|
restype
|
The return type of the method.
DEFAULT:
|
argtypes
|
The argument types of the method, as a
DEFAULT:
|
varargs
|
Variadic arguments for the method, as a
DEFAULT:
|
rubicon.objc.runtime.add_method
¶
add_method(cls, selector, method, encoding, replace=False)
Add a new instance method to the given class.
To add a class method, add an instance method to the metaclass.
| PARAMETER | DESCRIPTION |
|---|---|
cls
|
|
selector
|
|
method
|
The method implementation, as a Python callable or a C function address.
|
encoding
|
The method's signature (return type and argument types) as
a
|
replace
|
If the class already implements a method with the given
name, replaces the current implementation if
DEFAULT:
|
| RETURNS | DESCRIPTION |
|---|---|
|
The ctypes C function pointer object that was created for the method's implementation. This return value can be ignored. (In version 0.4.0 and older, callers were required to manually keep a reference to this function pointer object to ensure that it isn't garbage-collected. Rubicon now does this automatically.) |
rubicon.objc.runtime.add_ivar
¶
add_ivar(cls, name, vartype)
Add a new instance variable of type vartype to cls.
rubicon.objc.runtime.get_ivar
¶
get_ivar(obj, varname, weak=False)
Get the value of obj's ivar named varname.
The returned object is a ctypes data object.
For non-object types (everything except objc_id
and subclasses), the returned data object is backed by the ivar's actual memory.
This means that the data object is only usable as long as the "owner" object is
alive, and writes to it will directly change the ivar's value.
For object types, the returned data object is independent of the ivar's memory.
This is because object ivars may be weak, and thus cannot always be accessed
directly by their address.