6

I want to use CFStreamCreatePairWithSocketToHost with NSInput- and OutputStreams. I have two ivars NSInputStream *_inputStream and NSOutputStream *_outputStream.

The following gives me two error messages:

CFStreamCreatePairWithSocketToHost(NULL,
  (__bridge_retained CFStringRef)self.hostname, self.port,
  (CFReadStreamRef *)&_inputStream, (CFWriteStreamRef *)&_outputStream);

error: cast of an indirect pointer to an Objective-C pointer to 'CFReadStreamRef *' (aka 'struct __CFReadStream **') is disallowed with ARC
error: cast of an indirect pointer to an Objective-C pointer to 'CFWriteStreamRef *' (aka 'struct __CFWriteStream **') is disallowed with ARC

How would I fix this? I tried using __bridge but I got similar error messages.

2 Answers2

4

Pass a pointer to actual CFReadStreamRef and CFWriteStreamRef variables, then cast when assigning to your NSTypes. Basically:

CFThingRef cfThing = NULL;
CFFunctionGetThing(&cfThing);
NSThing * nsThing = cfThing;

Of course, you'll have to add the appropriate bridge cast and do all appropriate reference count ops for cfThing.

justin
  • 104,054
  • 14
  • 179
  • 226
  • Is this the only way to do this? –  Jan 12 '12 at 11:44
  • @WTP Not sure - I've not spent much time with ARC to date. Wrap it! :) – justin Jan 12 '12 at 11:48
  • @WTP: Don't forget that the function will zap the previous content of _inputStream and _outputStream with its own new CRStreamRefs, so you might as well make them CFStreamRefs. – JeremyP Jan 12 '12 at 12:02
0

Think about what ARC is doing, and what __bridge casts do: ARC takes responsibility for retaining / releasing NSObjects. __bridge casts transfer that responsibility. For example, __bridge_retained retains an NSString, cast the pointer to CFStringRef, and handed the responsibility for doing the matching release operation to whoever uses the CFStringRef.

That cannot possibly work with a pointer to an NSObject* or a pointer to a Core Foundation ref. A pointer points to a memory location. Any kind of NSObject* or Core Foundation object could be stored there.

You need two variables, one for an NSInputStream* and one for a CFReadStreamRef. Use the appropriate bridge cast to move the NSInputStream* to the CFReadStreamRef. Now you have what you want, and can pass the address on.

gnasher729
  • 51,477
  • 5
  • 75
  • 98