Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
How to declare objc UnsafeMutablePointer ?
-
## Swift: getAudioConverterInput(packetCount:AVAudioPacketCount, inputStatus:UnsafeMutablePointer<AVAudioConverterInputStatus>) -> AVAudioBuffer?{ if let currentAudioFormat = currentAudioFormat, firstPackets = packets.first{ inputStatus.memory = .HaveData let buffer = AVAudioCompressedBuffer(format: currentAudioFormat, packetCapacity: packetCount, maximumPacketSize: Int(currentMaximumPacketSize)) } ## Python def conv_block(self,inNumberOfPackets,buffstat): # buffstat: 0-have data 1-no data 2-endOfStream 3-error print '@',inNumberOfPackets,buffstat return aBuff convblock=ObjCBlock(conv_block,restype=None,argtypes=[c_void_p,c_int32,c_void_p]) # or:convblock=ObjCBlock(conv_block,restype=None,argtypes=[c_void_p,c_int32,POINT(c_void_p)]) ? status = converter.convertToBuffer_error_withInputFromBlock_(outBuffer,None,convblock) print status
-
I don't know much about Swift, but an
UnsafeMutablePointer
is probably just a normal C pointer. In general I'd recommend looking at the Objective-C docs and not the Swift docs, because the Objective-C docs can be translated directly intoctypes
andobjc_util
code. With Swift docs, you also need to know how Swift works internally and how it interacts with Objective-C.The API reference for -[AVAudioConverter convertToBuffer:error:withInputFromBlock:] says that the third parameter is of type AVAudioConverterInputBlock, and that is declared as
typedef AVAudioBuffer * _Nullable (^AVAudioConverterInputBlock)(AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus *outStatus);
And AVAudioConverterInputStatus is an
enum
ofNSInteger
s (the API reference doesn't say that the enum type isNSInteger
, I had to look intoAVFoundation/AVAudioConverter.h
to find that out).NSInteger
is along
, so the correct type for the block's third parameter isctypes.POINTER(ctypes.c_long)
. -
@dgelessus
Thank you very much.
I need set buffstat (etc:buffstat=1), but how to define byref?using def conv_block(self,inNumberOfPackets,byref(buffstat)):
but it's error.
def conv_block(self,inNumberOfPackets,buffstat): # buffstat: 0-have data 1-no data 2-endOfStream 3-error print '@@@',inNumberOfPackets,ObjCInstance(buffstat) aBuff.frameLength = 1024 return aBuff convblock=ObjCBlock(conv_block,restype=None,argtypes=[c_void_p,c_int32,POINTER(c_long)])```
-
byref
is for passing pointers into a (Objective-)C function. Here you are writing an Objective-C block, which means that you getbuffstat
as a function argument.buffstat
is a pointer, which means that you can change its value like this:buffstat.contents.value = 0
-
@dgelessus It's work. Thank you.
def conv_block(self,inNumberOfPackets,buffstat): # buffstat: 0-have data 1-no data 2-endOfStream 3-error print '@1',inNumberOfPackets,buffstat.contents.value buffstat.contents.value = 1 print '@2',inNumberOfPackets,buffstat.contents.value aBuff.frameLength = 1024 return aBuff convblock=ObjCBlock(conv_block,restype=None,argtypes=[c_void_p,c_int32,POINTER(c_long)])
-
@dgelessus The other question.
below code,how can call instantiateWithComponentDescription_options_completionHandler_ ?
- (void)instantiateWithComponentDescription:(AudioComponentDescription)audioComponentDescription
options:(AudioComponentInstantiationOptions)options
completionHandler:(void (^)(__kindof AVAudioUnit *audioUnit, NSError *error))completionHandler;
AVAudioUnit=ObjCClass('AVAudioUnit') AVAudioUnitComponent=ObjCClass('AVAudioUnitComponent') AVAudioUnitComponentManager=ObjCClass('AVAudioUnitComponentManager') class AudioComponentDescription(ctypes.Structure): _fields_=[('componentType',ctypes.c_uint32),('componentSubType',ctypes.c_uint32),('componentManufacturer',ctypes.c_uint32),('componentFlags',ctypes.c_uint32),('componentFlagsMask',ctypes.c_uint32)] def conver_OSType(c4str): return struct.unpack('I',bytes(c4str[::-1]))[0] def AVAudioUnitComp(self,avAudioUnit,error): self.effect = ObjCInstance(avAudioUnit) self.engine.attachNode(self.effect) AVAudioUnitComp1=ObjCBlock(AVAudioUnitComp,restype=None,argtypes=[c_void_p,c_void_p,c_void_p]) anyEffect = AudioComponentDescription(conver_OSType('aufx'),conver_OSType('dcmp'),0,0,0) manager=AVAudioUnitComponentManager.sharedAudioUnitComponentManager() # Return AVAudioUnitComponent[] availableEffects = ObjCInstanceMethod(manager,'componentsMatchingDescription_')(anyEffect, argtypes=[AudioComponentDescription],restype=c_void_p) print availableEffects[0].audioComponentDescription() # print Result: <objc_util.AudioComponentDescription_Structure object at 0x11077f048> AVAudioUnit.instantiateWithComponentDescription_options_completionHandler_(ObjCInstance(availableEffects[0].audioComponentDescription()),1,AVAudioUnitComp1) # Error !!!: TypeError: unhashable type AVAudioUnit.instantiateWithComponentDescription_options_completionHandler_(availableEffects[0].audioComponentDescription(),1,AVAudioUnitComp1) # Error !!!: ArgumentError: argument 3: <type 'exceptions.TypeError'>: expected AudioComponentDescription_Structure instance instead of AudioComponentDescription_Structure
- (void)instantiateWithComponentDescription:(AudioComponentDescription)audioComponentDescription
-
unhashable type means you tried to pass a Structure to ObjCinstance. ObjCInstance can only be created from a pointer, another ObjCInstance, or from a python object that has an _objc_ptr (like ui.View's). Your function signature says it takes a structure, not an ObjCInstance. You have had this error a few times in the last few threads, it is an easy mistake to make when mixing objects and structures...
The second problem is due to the way structures are handled in ctypes and objc_util.... the auto-generated structure generated by objc_util is not the same structure technically as the one you created manually. So, you need to override both argtypes and restype to specify your version of the structure. I think you had a similar problem in a recent thread. Alternatively, you need to interrogate the argtypes (using parse_type_encoding iirc) to get the class that you can use to create structures that conform.
(@omz this would be a good enhancement for objc_util when dealing with structure args --when the auto-type and the user provided structure don't match, a pointer to the user provided structure should be cast to a pointer of the auto-generated structure then derefernced... possibly with some sizeof checks to catch stupid errors)
-
I found this omz demo code, and run it on Pythonista V3 (iPad Pro 9.7 iOS10 system). but had some error.
(AttributeError: '__Structure' object has no attribute 'x')# https://forum.omz-software.com/topic/3030/get-data-from-objc_util-__structure/2 from objc_util import * from ctypes import Structure, c_double import time class CMRotationRate (Structure): _fields_ = [('x', c_double), ('y', c_double), ('z', c_double)] CMMotionManager = ObjCClass('CMMotionManager') mgr = CMMotionManager.alloc().init() try: mgr.startGyroUpdates() for i in range(10): time.sleep(1) gyro_data = mgr.gyroData() if not gyro_data: print('data not available (yet?)') continue # Using the custom struct here: rate = gyro_data.rotationRate(argtypes=[], restype=CMRotationRate) # You can now access the struct's fields as x, y, z: print(rate.x, rate.y, rate.z) # AttributeError: '__Structure' object has no attribute 'x'. # change to print(rate.a, rate.b, rate.c) it's ok # you can using print dir(rate) show it finally: mgr.stopGyroUpdates() mgr.release()
-
some information for structure.
# old method class AudioComponentDescription(ctypes.Structure): _fields_=[('componentType',ctypes.c_uint32),('componentSubType',ctypes.c_uint32),('componentManufacturer',ctypes.c_uint32),('componentFlags',ctypes.c_uint32),('componentFlagsMask',ctypes.c_uint32)] # New method from collections import namedtuple AudioComponentDesc = namedtuple("AudioComponentDesc", "componentType componentSubType componentManufacturer componentFlags componentFlagsMask") anyEffect_o = AudioComponentDescription(conver_OSType('aufx'),conver_OSType('dcmp'),conver_OSType('appl'),0,0) anyEffect_n = AudioComponentDesc(conver_OSType('aufx'),conver_OSType('dcmp'),conver_OSType('appl'),0,0) # using old method call this function will error,new method it's ok. availableEffects = manager.componentsMatchingDescription_(anyEffect_n) # but objc function return it's all fail. AVAudioUnit.instantiateWithComponentDescription_options_completionHandler_(availableEffects[0].audioComponentDescription(),1,AVAudioUnitComp1) # if using this will ok AVAudioUnit.instantiateWithComponentDescription_options_completionHandler_(anyEffect,1,AVAudioUnitComp1)