[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: __NSCF** classes and libobjc2 dependency on C++ runtime

From: Maxthon Chan
Subject: Re: __NSCF** classes and libobjc2 dependency on C++ runtime
Date: Wed, 05 Jun 2013 03:47:43 +0800

A humble test report:

TechniMac:test-poke technix$ cat test.m
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>

int main(void)
CFStringRef string = CFSTR("string");
NSString *bridged_string = (__bridge id)string;
NSLog(@"Bridged class: %@", NSStringFromClass([bridged_string class]));

CFRunLoopRef runloop = CFRunLoopGetMain();
id bridged_runloop = (__bridge id)runloop;
NSLog(@"Unbridged class: %@", NSStringFromClass([bridged_runloop class]));
return 0;
TechniMac:test-poke technix$ xcrun clang -framework Foundation -framework CoreFoundation -fobjc-arc test.m -o test
TechniMac:test-poke technix$ ./test 
2013-06-05 03:46:46.645 test[39422:707] Bridged class: __NSCFConstantString
2013-06-05 03:46:46.662 test[39422:707] Unbridged class: __NSCFType
TechniMac:test-poke technix$ 

在 2013-6-5,上午3:00,Stefan Bidi <address@hidden> 写道:

As the AWOL maintainer of CoreBase, I guess I can chime in on the CF/toll-free bridging stuff...

Originally, I did use the ISA pointer as the type ID, this however doesn't work everywhere.  For none toll-free bridged types, the ISA pointer is always set to NSCFType, so you end up with multiple CF types having the same ObjC class.  This class responds to some basic messages and allows all CF types to be retained/released by ObjC-only code, for example.

Even though I haven't had time to work on CoreBase in quite some time, I still encourage people to submit patches and ideas.  Please keep in mind, however, that the project has been around for over 3 years now, and in that time quite a few important design decisions were made.  The most important of all being how CF types interact with ObjC classes (i.e. bridging).  In this particular case, things are done the way they are done because it is the only sensible way without having tons special cases.


On Tue, Jun 4, 2013 at 1:19 PM, Maxthon Chan <address@hidden> wrote:
I never intend to do what Apple did in their exact way. That is illegal even in PRC. My intention is to a) write test cases around documented API that both GNUstep and Apple have and capture what Apple emit from them and b) replicate this result in a reasonable way using GNUstep, not caring if the implementation detail is the same. If I ended up doing it the exact way, well lucky me… I have no idea how Apple did that unless it is something open-sourced (and I guess I can link LGPL code against APSL code, right?) and I have no intention to clone it in a full blown way, just the surface behavior.

So before I say anything more, just giving an example, in my implementation of toll-free bridging the "type ID" is useless, as CoreFoundation objects are identified by their companion classes. Here is a sneak peek of what my propose is.

@protocol GSTollFreeBridging <NSCopying, NSObject>

- (CFTypeID)typeID;

// ...


// Here is an example of toll-free bridged object, NSString versus CFString

@interface NSString : NSObject <GSTollFreeBridging>

// …


@interface GSCFString : NSString


typedef struct __CFString
Class isa;
// ...
char *buf;
// …
} *CFStringRef;

CFStringRef CFSTR(consr char *str)
// Just being quick and dirty
CFStringRef string = malloc(sizeof(struct __CFString));
memset(string, 0, sizeof(struct __CFString));
string->isa = [GSCFString class];
// …

CFTypeID CFGetTypeID(CFTypeRef obj)
id<GSTollFreeBridge> self = (__bridge id)obj;
return [self typeID];

CFTypeRef CFRetain(CFTypeRef obj)
return (__bridge CFTypeRef)objc_retain((__bridge id)obj); // Oh yes, ARC-enabled.

void CFRelease(CFTypeRef obj)
objc_release((__bridge id)obj);

@implementation GSCFString

- (void)dealloc
CFStringRef string = (__bridge CFStringRef)self;
if (string->buf)
string->buf = NULL;
// …

// …


// Here is an example of non-TFB'd object, CFRunLoop. It will have an isa pointer of this class.

@interface GSCFRunLoop : NSProxy <GSTollFreeBridge>

// …


在 2013-6-5,上午1:52,Ivan Vučica <address@hidden> 写道:


On 4. 6. 2013., at 19:27, Maxthon Chan <address@hidden> wrote:

My reason on saying that you may not be clear what Apple is doing:

It seemed to me that you have totally ignored what happened in the Apple land in the recent years. What you did matched 10.6 behavior (I still have a 10.6.7 disk with Xcode 3.x lying around somewhere and I have hacked my VMware Fusion installation) but in 10.7 and 10.8 Apple changed a lot. Did you notice that in 10.8 CoreFoundation is linked against libobjc on both i386 and amd64, in 10.7 only amd64, but in 10.6 it was not?

I'm sure most of the GNUstep community is very confident both Apple and David know what they are doing, and that David knows just enough about what Apple is doing without compromising his or GNUstep's legal position :-)

Besides, why is this technical detail about library relationships important? We need to have similar behavior, not exact implementation. If GNUstep does or can do things differently without confusing the end user or breaking expectations, that's better from a legal (and, perhaps more importantly, moral!) standpoint.

I'm all for as much compatibility with Apple implementation as possible. But, I was told enough times on these very lists that GNUstep doesn't need to be a clone of anything. And I agree.

My Core Animation implementation, for example, does not do things "the Apple way". And I mean that on the deepest level. One can accidentally, without digging, see in the backtrace of a crashing program that Apple implemented Core Animation in C++. I didn't. Their implementation will perhaps be faster even when the GNUstep implementation is optimized and reoptimized and reoptimized. My implementation, however, does not really have to differentiate between animatable and non-animatable properties too much. I don't know if theirs internally does; but their docs talk about it as if it does.

Well before you ban me for "legal reasons":

1) Apple exposed and documented all the interfaces I used to learn its internals (Actually Apple are never good at hiding them.). The poking-around code can even be accepted to iOS App Store, as someone on StackOverflow have previously did, multiple times. (And you know that Apple rejects any code that violates their T&C from App Store.)

I attended Stallman speeches here in Zagreb, one of them relating to patents.

Let's just say that sometimes you don't even have to study someone's code to be infringing on a patent.

And Apple has DEFINITELY accepted a lot of things that they later pulled; even their own rulebook says that thing happens. For example, recently they let through a full-blown emulator, something they really don't like. That doesn't mean we should take it for granted.

2) All conclusion is based on what I fed into the public API and what it spit out, like NSLog("%@", NSStringFromClass([(__bridge id)CFSTR("foo") class])); - I dumped whatever it spit out from NSStringFromClass() function given I fed it a class from a toll-free bridged CoreFoundation object. This is at most like writing test cases around it.

This, I think, is good enough, as long as you don't go out of your way to replicate exact implementations.

3) No Apple code is used. I don't even have access to them, and I am not interested in reverse engineering it. And whatever code I may commit is at most mimicking Apple's behavior, based on whatever the previous experiments tell me. That is, after I captured what Apple code emit from my experiments, I write code to make GNUstep (my own fork) libraries do the same. (well, maybe __NSCF* became GSCF*) with the same parameters.

Of course you don't have access, that's the 'reverse engineering' part :-)

It's a thin line between reimplementing and outright cloning, though. David is making a very strong point here about GNUstep already having a different implementations of the runtime, with its own strengths and weaknesses compared to Apple's implementation. Do we need to replicate every detail of their implementation? :-)

Just an interesting side note about this, there is a tool called classdump that will dump framework header files from Objective-C binaries, its sole purpose is to reverse engineering, but it faced zero issue from Apple. And what I did does not even involve that.

Sure, the primary purpose of classdump is reverse engineering. At issue is what's done after dumping the headers :-)

Most people do useful stuff on Apple platforms; I'm sure Apple won't object too loudly to, for example, Dropbox hacking into Finder to deliver better experience.

If a different implementation of one of their main products starts poking deep into the system in order to replicate it? Well, you know what happened to Samsung for replicating visual identity.

And if Apple intend to sue anyone, let them sue me, in the US Calif. laws. (I am currently a citizen of P.R. China, and fighting a copyright lawsuit is not exactly easy here for Apple - laws are steered in a way that it may protect natives when foreigners sue natives.)

Now, now. That's actually not a nice statement from you. Although it might seem selfless, it's in fact selfish.

Imagine the "risky" knowledge you obtained gets used by a company in a commercial product. (Neither GPL nor LGPL object to commercial use within their terms.) Now, this company gets in trouble. You're safe inside P.R.C.; what about this U.S. or U.K. company? What's the legal climate in Japan?

It's good that GNUstep keeps caring about legal issues; this makes it more possible that someday a new midsize or large corporate contributor appears and joins the party.

Gnustep-dev mailing list

reply via email to

[Prev in Thread] Current Thread [Next in Thread]