Thanks for your time @JonB, running things on the console was super useful, it actually shows you all the members and functions of the objc variables.
I'm still having issues with getting the device. I tried wrapping the return value ObjCInstance(mtlView.device()) but it still returns a number, specifically <b'__NSCFNumber': 137478144> Apple docs say MTLCreateSystemDefaultDevice should return an object that follows the MTLDevice protocol. So could this number be a pointer or a memory address for where the actual device object is located or am I not supposed to get a number?
Edit: Nvm, wrapping the int with ObjCInstance does do the trick. I'm getting the A9 gpu device. I think it didn't work earlier because the order of the code.
Update: After finding the device I was able to find the correct function names and I’m proud to say we got the screen clearing to a color lol. Thanks again for all the input
Updated code:from objc_util import * import ui import ctypes load_framework('MetalKit') MTKView = ObjCClass('MTKView') MTLCreateSystemDefaultDevice = c.MTLCreateSystemDefaultDevice MTLCreateSystemDefaultDevice.argtypes =  MTLCreateSystemDefaultDevice.restype = c_void_p main_view = ui.View() w, h = ui.get_screen_size() main_view.name = 'Metal Demo' view = ObjCInstance(main_view) mtlView = MTKView.alloc().init() mtlView.setFrame_(CGRect((0, 0), (w, h))) mtlView.setClearColor_((0.2, 0.8, 0.44, 1.0)) mtlView.device = ObjCInstance(MTLCreateSystemDefaultDevice()) device = mtlView.device() view.addSubview_(mtlView) commandQueue = device.newCommandQueue() commandBuffer = commandQueue.commandBuffer() commandEncoder = commandBuffer.renderCommandEncoderWithDescriptor_(mtlView.currentRenderPassDescriptor()) commandEncoder.endEncoding() commandBuffer.presentDrawable(mtlView.currentDrawable()) commandBuffer.commit() if __name__ == '__main__': main_view.present(hide_title_bar=True)