How to call objc function
How to call objc function (not class).
You have to "load" the function from the c library and manually set the return- and argument-types.
If the function returns an object, your fine, but if it returns a c struct, you'll have to recreate this struct in a Python class. example script that does this
from ctypes import *
c = cdl.LoadLibrary(None)
@wolf71 you need to set the return tupe, and argtypes, though in this case argtypes=.
c = cdll.LoadLibrary(None)
@JonB Thank you.
@JonB How to get the ios default values?
etc: get NSDefaultRunLoopMode values
@wolf71 since most of these are defined as constants or macros, it's difficult to get their value at runtime. The easiest solution would be to pass the "raw" value of the constant in your code, instead of the constant itself. You can create a new playground in Xcode and just log the constant.
If it's an enum, you usually can just look at the documentation and count which case you need (they're represented by integers starting at 0)
@JonB How can defind a struct for objc?
etc: AudioStreamBasicDescription (it's objc structure).
and using this to init. init(mSampleRate:mFormatID:mFormatFlags:mBytesPerPacket:mFramesPerPacket:mBytesPerFrame:mChannelsPerFrame:mBitsPerChannel:mReserved:)
etc: get NSDefaultRunLoopMode values
Many constants can be found using in_dll for the appropriate ctypes type. For instance, NSDefaultRunLoopMode is declared as a NSString, therefore the appropriate ctypes type is a c_void_p. Calling ObjCInstance then gives you the object.
It really seems like you are doing things the hard way... not sure what you are trying to actually do, but if you just want to create a thread, using
Since this is declared as a STRUCT and not an object, you need to use a ctypes struct.
import ctypes class AudioStreamBasicDescription(ctypes.Structure): _fields_=[('mSampleRate',ctypes.c_double), ('mFormatID',ctypes.c_uint32), ('mFormatFlags',ctypes.c_uint32), ('mBytesPerPacket',ctypes.c_uint32), ('mBytesPerFrame',ctypes.c_uint32), ('mBitsPerChannel',ctypes.c_uint32), ('mReserved',ctypes.c_uint32)]
You initialize by passing positional or keyword arguments, or just init and set attributes.
bd=AudioStreamBasicDescription() #all zeros bd.mSampleRate=11025 or bd=AudioStreamBasicDescription(11025, ........) or bd=AudioStreamBasicDescription(mSampleRate=11025, ........)
are all basically the same.
Obviously, you need to figure out the right flags, etc to use. You may need to us a variation of
import struct struct.unpack('L', b'lpcm')
for the formatId, see the apple docs for the right 4 char code.
This code crash.
** initWithStreamDescription:(const AudioStreamBasicDescription *)asbd
** The AVAudioFormat need this type: <objc_util.LP_AudioStreamBasicDescription_Structure object at 0x10d02c148>
but the AudioStreamBasicDescription is <main.AudioStreamBasicDescription object at 0x110512048>
class AudioStreamBasicDescription(ctypes.Structure): _fields_=[('mSampleRate',ctypes.c_double),('mFormatID',ctypes.c_uint32),('mFormatFlags',ctypes.c_uint32),('mBytesPerPacket',ctypes.c_uint32),('mFramesPerPacket',ctypes.c_uint32),('mBytesPerFrame',ctypes.c_uint32),('mChannelsPerFrame',ctypes.c_uint32),('mBitsPerChannel',ctypes.c_uint32),('mReserved',ctypes.c_uint32)] outformat = AVAudioFormat.alloc().initWithStreamDescription_(AudioStreamBasicDescription(44100,1,0,0,0,0,2,0,0))
This is a case where you need to override argtypes to point to your structure definition, since the auto definition will not match yours.
Also, I am pretty sure your formatID is invalid. I think you need the four byte code described in the apple docs.
Actually... for what its worth, consider using one of the initWithCommonFormat or initWithStandardFormat methods, which eliminate the need to create your own stream description.
other question: how to define a NSUinteger * var?
# getBuffer:(uint8_t * _Nullable *)buffer length:(NSUInteger *)len aabuf = c_char_p() aalen = c_ulong() inStream.getBuffer_length_(aabuf,aalen)
Error: type 'exceptions.TypeError'>: expected LP_c_ulong instance instead of c_long
@wolf71 In this case you need to pass both arguments using
byref. The first argument (
buffer) is a pointer-to-pointer-to-char, and
aabufis a pointer-to-char, so you need to use
byrefto make it a pointer-to-pointer. Same with the next one -
lenneeds to be a pointer-to-long, and
aalenis a long, so you need to put it through
byrefto make it a pointer.