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.
Objcblock restype define question.
-
Define a objc function.
typedef AVAudioBuffer * _Nullable (^AVAudioConverterInputBlock)(AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus *outStatus);Just like below code,but when return inBuffer data (<AVAudioPCMBuffer@0x1702091f0: 0/8192 bytes>) it's crash. Return None it's ok.
typedef AVAudioBuffer * _Nullable -> restype = c_void_p ??
def conv_block(self,inNumberOfPackets,buffstat): # buffstat: 0-have data 1-no data 2-endOfStream 3-error buffstat.contents.value = 0 return inBuffer #ctypes.cast(inBuffer,ctypes.c_void_p) # return None ok, but return inBuffer crash!! return ctypes.cast(inBuffer,ctypes.c_void_p) crash!! convblock=ObjCBlock(conv_block,restype=c_void_p,argtypes=[c_void_p,c_int32,POINTER(c_long)]) # if using restype = POINTER(c_void_p) , return TypeError: invalid result type for callback function status = converter.convertToBuffer_error_withInputFromBlock_(outBuffer,error,convblock) print '>>Ret1:',status,outBuffer if error: print '>>Err:',ObjCInstance(error)
-
@wolf71 said:
status = converter.convertToBuffer_error_withInputFromBlock_
As usual, an example getting to this point would be useful. Does the uncaught exception handler provide any clues, or just st seg fault?
You might try returning pointer(inBuffer), since the type seems to be asking for a pointer to an AVAudioBuffer.
-
- Just seg fault.
Fatal Python error: Segmentation fault
Thread 0x000000016e14f000 (most recent call first):
2.I try return pointer(inBuffer), error,
so using pointer(ctypes.cast(inBuffer,ctypes.c_void_p)), error: Exception in <function conv_block at 0x10d9306d8> ignored-
the restype = c_void_p it's right? or need using other?
-
inBuffer is AVAudioBuffer.
- Just seg fault.
-
c_void_p(addressof(inBuffer))
or
cast(pointer(inBuffer),c_void_p)
or possibly just
addressof(inBuffer)
, but I am not sure about the last one...alternatively, what type does python think inBuffer is? Is it a custom Structure, or a c_void_p, etc? If it is a structure, you could set restype=POINTER(your_custom_struct), and then return pointer(inBuffer).
-
@JonB said:
-
ctypes.addressof(inBuffer) TypeError: invalid type
ctypes.cast(pointer(inBuffer),c_void_p) TypeError: type must have storage info -
maybe the restype = c_void_p is wrong, because c_void_p is int/long or None,but the <AVAudioBuffer> * Nullable it's a buffer. not int/long.
-
-
You will need to post actual code that got you this far. Where did you get inBuffer.
print(type(inBuffer))
-
@JonB
<class 'objc_util.ObjCInstance'> -
Can you post a gist of your code... it would help to be able to help, otherwise I am just throwing around guesses.
inBufferPtr=c_void_p(inBuffer.ptr) ... restype=POINTER(c_void_p) ... return pointer(inBufferPtr)
-
@JonB Test Code it's here.
# -*- coding: utf-8 -*- from objc_util import * import ctypes,time,os,struct,array,console # AVAudio Define AVAudioEngine=ObjCClass('AVAudioEngine') AVAudioSession=ObjCClass('AVAudioSession') AVAudioUnit=ObjCClass('AVAudioUnit') AVAudioPlayerNode=ObjCClass('AVAudioPlayerNode') AVAudioFile=ObjCClass('AVAudioFile') AVAudioPCMBuffer=ObjCClass('AVAudioPCMBuffer') AVAudioUnitEffect=ObjCClass('AVAudioUnitEffect') AVAudioFormat=ObjCClass('AVAudioFormat') AVAudioCompressedBuffer=ObjCClass('AVAudioCompressedBuffer') AVAudioConverter=ObjCClass('AVAudioConverter') # AVAudioFormat: 0-other,1-PCM float32,2 PCM float64,3-PCM int16,4-PCM int32 informat = AVAudioFormat.alloc().initWithCommonFormat_sampleRate_channels_interleaved_(3,44100,2,False) outformat = AVAudioFormat.alloc().initWithSettings_(ns({'AVSampleRateKey':44100,'AVNumberOfChannelsKey':2,'AVFormatIDKey':struct.unpack('I', b' caa')[0]})) # ,'mFramesPerPacket':1024})) inBuffer = AVAudioPCMBuffer.alloc().initWithPCMFormat_frameCapacity_(informat,4096) converter = AVAudioConverter.alloc().initFromFormat_toFormat_(informat,outformat) outBuffer = AVAudioCompressedBuffer.alloc().initWithFormat_packetCapacity_maximumPacketSize_(outformat, 8,converter.maximumOutputPacketSize()) gcnt = 0 # typedef AVAudioBuffer * _Nullable (^AVAudioConverterInputBlock)(AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus *outStatus); def conv_block(self,inNumberOfPackets,buffstat): global gcnt # buffstat: 0-have data 1-no data 2-endOfStream 3-error print '@1',inNumberOfPackets,buffstat.contents.value gcnt += 1 if gcnt == 1: buffstat.contents.value = 0 print '@2',inNumberOfPackets,buffstat.contents.value print '!!! InBuff:',inBuffer,type(inBuffer),ctypes.cast(inBuffer,ctypes.c_void_p) #,ctypes.addressof(inBuffer) return None #pointer(c_void_p(inBuffer.ptr)) else: buffstat.contents.value = 2 return None #convblock=ObjCBlock(conv_block,restype=POINTER(c_void_p),argtypes=[c_void_p,c_int32,POINTER(c_long)]) convblock=ObjCBlock(conv_block,restype=c_void_p,argtypes=[c_void_p,c_int32,POINTER(c_long)]) error=ctypes.c_void_p(0) status = converter.convertToBuffer_error_withInputFromBlock_(outBuffer,error,convblock) print '>>Ret1:',status print '>>out1:',outBuffer if error: print '>>Err:',ObjCInstance(error) status = converter.convertToBuffer_error_withInputFromBlock_(outBuffer,None,convblock) print '>>Ret2:',status print '>>out2:',outBuffer
-
if using restype=POINTER(c_void_p)
Error:
PythonistaKit.framework/pylib/site-packages/objc_util.py", line 955, in init
block.invoke = InvokeFuncType(func)
TypeError: invalid result type for callback function -
@JonB I Try Using this, it's ok.
return inBuffer.ptr
convblock=ObjCBlock(conv_block,restype=c_void_p,argtypes=[c_void_p,c_int32,POINTER(c_long)])
-
@JonB other question.
the outBuffer.data() is a UnsafeMutableRawPointer,
print outBuffer.data() # >>> c_void_p(4635022848) # I need get data,so using oData = ObjCInstance(outBuffer.data()) # but Pythonista crash.
How Can get the data?
-
here is an example i found
http://stackoverflow.com/questions/13723384/audioconverter-number-of-packets-is-wrongdata looks undocumented, you need to go through the audioBufferList, imthink.
For dealing with pointers to buffers, there are a few ways, depening on how you want to fill the data. For the buffer you have to create, probably c_buffer(lengthInBytes) creates the buffer, then use addressof or pointer to get a pointer to the buffer.
For the one you need to read, cast to a (c_charlengthBytes), or use (c_charlengthBytes).from_address, then use regular slicing to access the contents as bytes.
-
@JonB Thanks.
tbuf = (ctypes.c_int16*1024).from_address(outBuffer.data().value) # Not error,and using tbuf[1] can get data. # It's right ??