apy.pyx
June 18, 2025 ยท View on GitHub
api.pyx is a cython 'builtin' module which wraps parts of the Max/MSP c-api
for the py external.
The api module consists of:
- api.pyx: main cython wrapper
- a number of cython declaration files (.pxd) which expose c headers
- api_max.pxd: exposes Max api headers
- api_msp.pxd: exposes MSP api headers
- api_jit.pxd: exposes Jitter api headers
- api_py.pxd: exposes the py external's headers
Cython classes, functions, and constants defined here are optionally
available for use by python code running in a py external instance.
Wrapper Classes
There are several class types:
-
Generic classes which are meant to be used as superclasses, wrapping
t_object*pointers-
AbstractMaxObject: abstract class for basic t_object* based object -
MaxObject: Base wrapper for Max t_object* objects
# generic objet class usage # has signature o = api.Object(classname, name, *args, **kwds) # for example c = api.Object("coll", "mycol", embed=True) # Another variant is to be used as superclass # has signature o = api.AbstractObject(name, *args, **kwds) class Coll(AbstractObject): # ... -
-
Specialized classes with their own c-api methods and type-specific pointer types. These are documented in the Max-api docs:
Atom: Wrapper for Max mx.t_atom* atoms/messagesTable: Interface to Max tablesBuffer: Interface to MSP buffersDictionary: Interface to Max dictionariesDatabaseView: Interface to Max database viewsDatabaseResult: Interface to Max database resultsDatabase: Interface to Max databasesList: Interface to Max linked listsBinbuf: Interface to Max binbufsAtombuf: Interface to Max atom buffersHashtab: Interface to Max hash tablesAtomArray: Interface to Max atom arraysPatcher: Interface to Max patchersBox: Interface to Max boxes/objectsMatrix: Interface to Max jit matricesPath: Interface to Max path handlingMaxApp: Interface to the Max application
-
High-level wrapper: these can only be invoked in the max c-apu using generic object methods and subclass (1) generic classes. An example of this is the
api.Collclass -
External wrappers: these wrap the
pyexternal itself:PyExternal: Main interface for thepyexternalPyMxObject: Alternative external extension type (obj pointer retrieved via uintptr_t)
Features
-
Provides access to max c-api functionality in an interpreted language.
-
Wraps a decent subset of the max c-api for python code running in a
pyexternal instance. -
Write max methods in cython which can be called in c
-
All c is exposed via cython to python
-
Wrap max types as cython extension classes, e.g.
api.Atom,api.Patcher, .. -
Errors in python don't crash Max (or crash max less!)
Design Notes
-
to refactor the object_method_typed calls which are being duplicated in
Patcher,MaxObect,MaxApp, etc.. -
There should be sufficient number of wrapper classes (which wrap pointers) to enable productive scripting. So instead of returning a
mx.t_object*one returns aMaxObject
Usage
Either
-
Send the
pyobject animport apimessage or -
Import a module on the pythonpath which imports the
apimodule or -
Send a
(load <file.py)message to load a file on the Max search path which contains python code that imports theapimodule. Then; -
Call one of the functions or classes in this file making sure to prefix it with
api.
1.
( import api )
|
| 2.
[ py ] ------ ( api.post('hello world') )
Development
A lot of the painful laborious work of creating header mappings has been
done and can be reviewed (and corrected) in
the api_max.pxd and api_msp.pxd files.
This provides the benefit that we can import the max api via its header declarations as follows:
cimport api_max as mx
Then you can start using Max api symbols or functions in the cython code
by prefixing with mx. For example
gensym() -> mx.gensym()
post() -> mx.post()
...
In addition the py external api is also mapped for use by cython
(see below) in api_py.pxd file:
cimport api_py as px
Again please note any function exposed from the py external must
be prefixed as px:
py_scan() -> px.py_scan()
This separation of namespaces is clearly very useful when you are wrapping code.
Extension Types
We use cython extension types to wrap related C data structures and functions in the Max api. This them accessible to python code and gives them a python-friendly interface.
So far the following extension types are implemented (partial or otherwise)
- MaxObject
- Atom
- Table
- Buffer
- Dictionary
- Database
- DatabaseResult
- DatabaseView
- Linklist
- Binbuf
- Atombuf
- Hashtab
- AtomArray
- Patcher
- Box
- Buffer
- PyExternal
- MaxApp
Workarounds for max types which are not exposed in the c-api:
-
coll: import and export the contents of acollinto adictby sending a message to thedictobject. -
jit.cellblock: link acollto acellblockand data sent to thecollwill be sent to thecellblock. -
jit.matrix: can be populated viajit.fillfrom acoll