Class dump and CFObjects - objective-c

Does class dump get confused by CFObjects/structs? I used class dump on an application and one of the method's argument was a struct arg1 which is a BInstantMessage:
struct BInstantMessage {
void **_field1;
struct CFString _field2;
unsigned short *_field3;
struct DTextStyle _field4;
struct BUser *_field5;
struct BChat *_field6;
};
struct CFString {
void **_vptr$CFObject;
struct __CFString *mCFRef;
_Bool mIsMutable;
};
struct __CFString;
So, how can I get a CFStringRef or NSString* from this arg1? I am guess that class dump is replacing some CFStringRef by CFString definitions, but it's just a guess...
All I want is to get a CFStringRef from arg1 which is a BInstantMessage.
Thnaks!

The application is using a C++ wrapper for Core Foundation objects. the struct CFString in BInstantMessage is an object of this type. You want (NSString *)(arg1._field2.mCFRef).
The void **_vptr$CFObject field is the major hint here – it represents the vtable for a virtual superclass CFObject – combined with the common C++ m prefix naming convention.

Related

Pass pointer to var in C function from Swift

I have a C function in a file with name (Buffer is a C struct)
BufferInit(Buffer *buffer, int32_t size)
As I am moving to Swift, in my Swift class I declare a private var like
var buffer:Buffer?
and in init function I make a call like this
BufferInit(&buffer, 32)
But I get compilation errors, what is the correct way to achieve the same in Swift? I call call the same BufferInit from Objective-C without issues but Swift is messy.
EDIT: Here are details,
typedef struct {
void *buffer;
int32_t length;
int32_t tail;
int32_t head;
} Buffer;
Error is compiler is asking me to unwrap buffer and correct the code as(which I don't think is correct):
BufferInit(&buffer!, 32)
Your C function is imported to Swift as
func BufferInit(_ buffer: UnsafeMutablePointer<Buffer>!, _ size: Int32)
and you have to pass the address of a (initialized, nonoptional)
variable of type Buffer as an inout expression.
Structures imported from C have a default constructor in Swift which
initializes all members to zero, so you can write
var buffer = Buffer()
BufferInit(&buffer, 32)

When should we use two-dimensional pointer in objective c

I want to know when should we use two-dimensional pointer in objective c. I read a article about the runtime mechanism. The implementation details of method objc_msgSend is as follows:
Any NSObject objective has a attribute of isa which will point to the corresponding Class object.
#interface NSObject <NSObject> {
Class isa OBJC_ISA_AVAILABILITY;
}
Class objective is as follows:
struct objc_class {
Class isa;
Class superclass;
const char *name;
uint32_t version;
uint32_t info;
uint32_t instance_size;
struct old_ivar_list *ivars;
struct old_method_list **methodLists; // Method list of the class
Cache cache;
struct old_protocol_list *protocols;
}
The question I want to ask is that why methodLists is two-dimensional pointer, what if we use one-dimensional or do not use pointer, can sb explain this question to me?Thanks in advance.
The struct old_method_list is as below:
struct old_method_list {
void *obsolete;
int method_count;
/* variable length structure */
struct old_method method_list[1]; //The address of the first Method
};
OK, I read another article about why old_method_list use two-dimensional pointer, the reason is that, it may point to an array.My another question is that for struct old_method method_list[1], the comment is "The address of the first Method", but method_list is an old_method array which length is 1. How it can store address?
I solved this question by reading another article.
The array struct old_method method_list[1] is dynamic, it can be changed by adding elements(methods) to it.
Because it points at array of pointers at old_method_list.
Update for old_method_list.
old_method_list * can point not just at old_method_list. It also can point at for example:
struct old_method_list_with_10_methods
{
struct old_method_list list;
struct old_method method_list[9];
};
Or if you need dynamic size:
old_method_list* list = malloc(sizeof(old_method_list) + (n-1) * sizeof(old_method));
list->method_count = n;
It's such variable length structure.

Casting an (NSString *) to (int *)?

I have an NSString.
NSString *str;
And I need to store it in a struct.
struct {
int *s;
} st;
And set it.
st.s = str;
So, how should I go about retrieving it?
return (__bridge_retained NSString *)st.s;
I've tried the above, and it gives the error: Incompatible types casting 'int *' to 'NSString *' with a __bridge_retained cast.
Answered the question. Simply define the NSString in the struct like this.
struct {
__unsafe_unretained NSString *s;
} st;
Thanks, Carl Veazey!
To store an Objective-C object in an struct you have a couple of options, the one I see most is to store it in the struct as __unsafe_unretained and then maintain a strong reference to it elsewhere.
From the "Common Issues While Converting a Project" section of the ARC Transition Notes:
If using Objective-C objects is sub-optimal, (maybe you want a dense
array of these structs) then consider using a void* instead. This
requires the use of the explicit casts...
They seem to imply __bridge is the way to cast void * to id but are not 100% clear on this.
The other option, which makes more sense to me personally and I've seen more often I think:
Mark the object reference as __unsafe_unretained. ... You declare the
structure as: struct x { NSString * __unsafe_unretained S; int X; }
Hope this helps!

typedef After anonymus enum declaration

I was looking at enums in cocoa frameworks and I saw this:
enum {
NSNetServiceNoAutoRename = 1UL << 0
};
typedef NSUInteger NSNetServiceOptions;
and my question is how is this possible?
How is NSNetServiceOptions tied to that enum?
And is it only possible in objective c or also in c?
NSNetServiceOptions tied to that enum in the context that the enum is going to hold an integer value anyway. In the above example you will create a variable for the enum as,
NSNetServiceOptions _netServiceOptions;
You can even ignore the typedef and directly use,
NSUIInteger _netServiceOptions;
enums in C (and consequently Obj-C and C++) are weakly typed, which means you can implicitly casts between enums and ints however you like as they are just ints.
For example, this is perfectly valid:
enum {A = 1};
enum {B = A+1};
const int C = A | B;
The reason the the enum uses a typedef instead of the shortform typedef enum {...} Name; is because enums defaults to being of type int. By using a typedef you can define the enum as being an unsigned integer instead.

How do you create a pointer to a struct and type cast it?

can someone tell me where I'm going wrong here? I'm trying to create a pointer to the struct aqData that is passed in to the function, and type type cast it to a struct type of AQPlayerState.
I'm getting the errors - Use of undeclared identifier "AQPlayerState" and Expected expression
#implementation AudioPlayer
#define kNumberBuffers 3
struct AQPlayerState {
AudioStreamBasicDescription mDataFormat;
AudioQueueRef mQueue;
AudioQueueBufferRef mBuffers[kNumberBuffers];
AudioFileID mAudioFile;
UInt32 bufferByteSize;
SInt64 mCurrentPacket;
UInt32 mNumPacketsToRead;
AudioStreamPacketDescription *mPacketDescs;
bool mIsRunning;
};
static void HandleOutputBuffer (
void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer
) {
struct AQPlayerState *pAqData = (AQPlayerState *) aqData;
Thanks in advance for any help
I believe Objective-C behaves as C. If it doesn't this might not apply to Objective-C.
structs in C are recognized by their "full name". Try
struct AQPlayerState *pAqData = (struct AQPlayerState *) aqData;
or, even better, don't cast at all. The C compiler knows how to convert from void* to any other pointer to object
struct AQPlayerState *pAqData = aqData;
implicit conversion: good
explicit conversion (cast): not so good