ObjC: Scheduling a stream on a run loop
I have a stream that shows status open, and accepts bytes that I write to it, but the delegate handler callback is not firing. I suspect I might not be scheduling the stream on the run loop properly:
I am especially unsure about the forMode parameter, which is supposed to be NSDefaultRunLoopMode global varuable. What is the right value to use in Python?
NSDefaultRunLoopModeis a global variable of type
NSRunLoopMode, which is a
NSString *. To get the value of that variable, you can do the following:
NSDefaultRunLoopMode = ObjCInstance(c_void_p.in_dll(c, "NSDefaultRunLoopMode"))
Then you can pass that object in the
forModepart of the method call.
0doesn't work because it's interpreted as a
NULLpointer, which probably isn't a valid argument here.
@dgelessus, ”extra credit” for leading me to the ctypes documentation and equipping me to maybe solve the next similar case myself.
Ah, seems I cannot do any objc stuff on my own...
This time the issue is that NSInputStream’s read:maxLength: needs a pointer to a buffer for storing the data coming from the stream. I have played with various ideas, including the following:
buffer = bytearray(1024) buf_p = ctypes.c_void_p.from_buffer(buffer) read_len = stream.read_maxLength_(buf_p, 1024)
... but all I get is a crash on read. Any pointers? Thanks!
from_buffermethod doesn't do what you think it's doing.
buffercontains data for a
c_void_p, and gives you a
c_void_pbacked by that data. Basically, it's not giving you a pointer to
buffer, it's interpreting the start of
bufferas a pointer. Since
bufferstarts out as all zeroes,
buf_pis a null pointer, so writing to it will crash.
I'm not quite sure, but you might be able to just pass
bufferdirectly into the method.
ctypesmight convert it to a pointer automatically - it does that for (read-only)
bytesobjects, I'm not sure if it works with
bytearrays as well.
If not, you can use
ctypes.create_string_bufferto create a new
c_chararray of the given length. This array can definitely be passed into C functions/methods. To get the data out of the array (after you've read into it), you can use the
rawattribute (to get the entire data) or the
valueattribute (to get everything up to the first zero byte - this is useful for C strings).
@dgelessus, thanks! Plain bytearray did not work, but create_string_array did, and I was able to create a bytearray out of its contents with the number of bytes read that read:maxLength: returns.