How do I get NSRect to be the same as CGRect?

  • In NSGeometry.h, there is some code that switches based on (__LP64__
    || NS_BUILD_32_LIKE_64), and if that's true, does:

    typedef CGRect NSRect;

    Otherwise, it defines NSRect explicitly. I don't understand why it
    does this, and it would make it easier if it just used the typedef.
    What do those flags mean, and is there a way for my code to get the
    typedef version?

    TIA,
    Rick
  • On Dec 16, 2007 3:46 PM, Rick Mann <rmann...> wrote:
    > In NSGeometry.h, there is some code that switches based on (__LP64__
    > || NS_BUILD_32_LIKE_64), and if that's true, does:
    >
    > typedef CGRect NSRect;
    >
    >
    > Otherwise, it defines NSRect explicitly. I don't understand why it
    > does this, and it would make it easier if it just used the typedef.

    Before Leopard, NSRect and CGRect were completely different types.
    Apple took the opportunity provided by the transition to 64-bit to
    eliminate the discrepancy. But this change could break binary
    compatibility, so it couldn't be done across the board for 32-bit
    code.

    > What do those flags mean, and is there a way for my code to get the
    > typedef version?

    Yes, just define NS_BUILD_32_LIKE_64. This was the first link on
    Google when searching for "NS_BUILD_32_LIKE_64":

    <http://developer.apple.com/documentation/Cocoa/Conceptual/Cocoa64BitGuide/6
    4BitChangesCocoa/chapter_3_section_3.html
    >

    --
    Clark S. Cox III
    <clarkcox3...>
  • On Dec 16, 2007, at 4:29 PM, Clark Cox wrote:

    > Before Leopard, NSRect and CGRect were completely different types.
    > Apple took the opportunity provided by the transition to 64-bit to
    > eliminate the discrepancy. But this change could break binary
    > compatibility, so it couldn't be done across the board for 32-bit
    > code.

    Really? NSGeometry.h defines NSRect like this (in the non-64-bit case):

    > typedef struct _NSPoint {
    > CGFloat x;
    > CGFloat y;
    > } NSPoint;
    >
    > typedef struct _NSSize {
    > CGFloat width;        /* should never be negative */
    > CGFloat height;        /* should never be negative */
    > } NSSize;
    >
    >
    > typedef struct _NSRect {
    > NSPoint origin;
    > NSSize size;
    > } NSRect;
    >

    And CGGeometry.h defines CGRect like this:

    > struct CGPoint {
    > CGFloat x;
    > CGFloat y;
    > };
    > typedef struct CGPoint CGPoint;
    >
    > /* Sizes. */
    >
    > struct CGSize {
    > CGFloat width;
    > CGFloat height;
    > };
    > typedef struct CGSize CGSize;
    >
    >
    > struct CGRect {
    > CGPoint origin;
    > CGSize size;
    > };
    > typedef struct CGRect CGRect;
    >

    Which seem to have identical layouts to me; that is, there should be
    no binary incompatibility. Furthermore, how could 32-bit portions of
    the API know if client code had defined it one way or another?

    In my own case, I did an ugly cast from NSRect to CGRect so that my
    existing C++ code could go ahead and draw. It seems to work fine.

    However, what I'd really like is for here to be a definition of NSRect
    that could be parsed by the C++ compiler (not having any Obj-C in it)
    so that my pre-existing Rect class could be made to easily be
    initialized from an NSRect.

    > Yes, just define NS_BUILD_32_LIKE_64. This was the first link on
    > Google when searching for "NS_BUILD_32_LIKE_64":
    >
    > <http://developer.apple.com/documentation/Cocoa/Conceptual/Cocoa64BitGuide/6
    4BitChangesCocoa/chapter_3_section_3.html
    > >

    I'm not really going for a 64-bit app here, and I understand there's
    some penalty for making an app 64-bit if you don't need it.

    --
    Rick
  • On Dec 16, 2007 4:56 PM, Rick Mann <rmann...> wrote:
    >
    > On Dec 16, 2007, at 4:29 PM, Clark Cox wrote:
    >
    >> Before Leopard, NSRect and CGRect were completely different types.
    >> Apple took the opportunity provided by the transition to 64-bit to
    >> eliminate the discrepancy. But this change could break binary
    >> compatibility, so it couldn't be done across the board for 32-bit
    >> code.
    >
    > Really? NSGeometry.h defines NSRect like this (in the non-64-bit case):
    >
    >> typedef struct _NSPoint {
    >> CGFloat x;
    >> CGFloat y;
    >> } NSPoint;
    >>
    >> typedef struct _NSSize {
    >> CGFloat width;            /* should never be negative */
    >> CGFloat height;          /* should never be negative */
    >> } NSSize;
    >>
    >>
    >> typedef struct _NSRect {
    >> NSPoint origin;
    >> NSSize size;
    >> } NSRect;
    >>
    >
    >
    > And CGGeometry.h defines CGRect like this:
    >
    >> struct CGPoint {
    >> CGFloat x;
    >> CGFloat y;
    >> };
    >> typedef struct CGPoint CGPoint;
    >>
    >> /* Sizes. */
    >>
    >> struct CGSize {
    >> CGFloat width;
    >> CGFloat height;
    >> };
    >> typedef struct CGSize CGSize;
    >>
    >>
    >> struct CGRect {
    >> CGPoint origin;
    >> CGSize size;
    >> };
    >> typedef struct CGRect CGRect;
    >>
    >
    >
    > Which seem to have identical layouts to me; that is, there should be
    > no binary incompatibility. Furthermore, how could 32-bit portions of
    > the API know if client code had defined it one way or another?

    You're forgetting C++ name mangling. To a C++ compiler, the difference
    is quite significant:

    void Foo(NSRect r);

    This function will have different names depending on whether or not
    NSRect is its own type or if it's just a typedef of CGRect.

    > In my own case, I did an ugly cast from NSRect to CGRect so that my
    > existing C++ code could go ahead and draw. It seems to work fine.
    >
    > However, what I'd really like is for here to be a definition of NSRect
    > that could be parsed by the C++ compiler (not having any Obj-C in it)
    > so that my pre-existing Rect class could be made to easily be
    > initialized from an NSRect.
    >
    >> Yes, just define NS_BUILD_32_LIKE_64. This was the first link on
    >> Google when searching for "NS_BUILD_32_LIKE_64":
    >>
    >> <http://developer.apple.com/documentation/Cocoa/Conceptual/Cocoa64BitGuide/6
    4BitChangesCocoa/chapter_3_section_3.html
    > > >
    >
    > I'm not really going for a 64-bit app here, and I understand there's
    > some penalty for making an app 64-bit if you don't need it.

    That's why that macro exists, for exactly your case: you want the
    types to be defined as they are on the 64-bit side, but you don't want
    to actually make it 64-bit.

    --
    Clark S. Cox III
    <clarkcox3...>
  • Clark Cox wrote:

    > You're forgetting C++ name mangling. To a C++ compiler, the difference
    > is quite significant:
    >
    > void Foo(NSRect r);
    >
    > This function will have different names depending on whether or not
    > NSRect is its own type or if it's just a typedef of CGRect.

    Is this the same reason for NSInteger being typedefed int under 32 bit, and
    typedefed long under 64 bit? I didn't see why we couldn't just use long
    everywhere and be done with it.

    Lachlan.
  • On Dec 16, 2007 7:41 PM, odela01 <lachlan.o'<dea...> wrote:
    > Clark Cox wrote:
    >
    >> You're forgetting C++ name mangling. To a C++ compiler, the difference
    >> is quite significant:
    >>
    >> void Foo(NSRect r);
    >>
    >> This function will have different names depending on whether or not
    >> NSRect is its own type or if it's just a typedef of CGRect.
    >
    > Is this the same reason for NSInteger being typedefed int under 32 bit, and
    > typedefed long under 64 bit? I didn't see why we couldn't just use long
    > everywhere and be done with it.

    Yes.

    --
    Clark S. Cox III
    <clarkcox3...>
  • Lachlan O'Dea wrote:

    > Is this the same reason for NSInteger being typedefed int under 32
    > bit, and
    > typedefed long under 64 bit? I didn't see why we couldn't just use
    > long
    > everywhere and be done with it.

    Because we wouldn't necessarily be done with it. The word 'long'
    means "at least 32 bits and not smaller than 'int'." Anything more
    specific than that is up to the implementation.
  • On 12/16/07 4:56 PM, Rick Mann said:

    > Which seem to have identical layouts to me;

    Yes, but nothing stops the compiler from padding or aligning CGRect
    differently from NSRect.  Of course, it's unlikely, but possible.  See '-
    fstrict-aliasing' in the gcc man page.

    So you should use NSRectToCGRect(), don't cast them!

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • On Dec 17, 2007, at 9:48 AM, Sean McBride wrote:

    > Yes, but nothing stops the compiler from padding or aligning CGRect
    > differently from NSRect.  Of course, it's unlikely, but possible.
    > See '-
    > fstrict-aliasing' in the gcc man page.

    It seems unlikely to me that the two structs would ever be treated
    differently by the compiler. I suppose an Objective-C compiler might
    treat it differently than C++, but for the Mac OS APIs that use NSRect
    to be built differently than client code that use NSRect, well, that
    would be unacceptable. The only other difference between them, then,
    is the name of the struct, which also would be an unacceptable
    influence on the actual layout of the struct.

    The more serious problem is that the C++ compiler cannot include the
    file defining NSRect; it contains Objective-C code. So, I can't make
    my Graphics::Rect class accept NSRects at all. It would be great if
    Apple could move NSRect to CGGeometry.h. Sigh.

    --
    Rick
  • On 12/17/07 12:52 PM, Rick Mann said:

    >
    > On Dec 17, 2007, at 9:48 AM, Sean McBride wrote:
    >
    >> Yes, but nothing stops the compiler from padding or aligning CGRect
    >> differently from NSRect.  Of course, it's unlikely, but possible.
    >> See '-
    >> fstrict-aliasing' in the gcc man page.
    >
    > It seems unlikely to me that the two structs would ever be treated
    > differently by the compiler. I suppose an Objective-C compiler might
    > treat it differently than C++, but for the Mac OS APIs that use NSRect
    > to be built differently than client code that use NSRect, well, that
    > would be unacceptable. The only other difference between them, then,
    > is the name of the struct, which also would be an unacceptable
    > influence on the actual layout of the struct.

    I agree it's unlikely, but the possibility is no doubt the reason for
    NSRectToCGRect() existing (it uses the union trick).

    > The more serious problem is that the C++ compiler cannot include the
    > file defining NSRect; it contains Objective-C code. So, I can't make
    > my Graphics::Rect class accept NSRects at all. It would be great if
    > Apple could move NSRect to CGGeometry.h. Sigh.

    Could you not make your Graphics::Rect class Objective-C++?  Just
    changing its extension should do the trick.

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • On Dec 17, 2007, at 1:04 PM, Sean McBride wrote:

    > I agree it's unlikely, but the possibility is no doubt the reason for
    > NSRectToCGRect() existing (it uses the union trick).

    I think that means that NSRectToCGRect() must take care to be compiled
    with the correct setting of -fstrict-aliasing.

    > Could you not make your Graphics::Rect class Objective-C++?  Just
    > changing its extension should do the trick.

    Perhaps, but it would limit its usefulness. All files that included
    the header file would need to use .mm as an extension.

    --
    Rick
  • On 12/17/07 1:11 PM, Rick Mann said:

    >> Could you not make your Graphics::Rect class Objective-C++?  Just
    >> changing its extension should do the trick.
    >
    > Perhaps, but it would limit its usefulness. All files that included
    > the header file would need to use .mm as an extension.

    What if, in your .h, you wrapped the APIs that need to use NSRect in an
    #ifdef __OBJC__ ?  That way, both .cp and .mm files can be clients?

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
  • On Dec 17, 2007, at 1:16 PM, Sean McBride wrote:

    > What if, in your .h, you wrapped the APIs that need to use NSRect in
    > an
    > #ifdef __OBJC__ ?  That way, both .cp and .mm files can be clients?

    Now, that might work. Thanks for the suggestion.

    --
    Rick
  • On Dec 17, 2007, at 3:11 PM, Rick Mann wrote:

    >
    > On Dec 17, 2007, at 1:04 PM, Sean McBride wrote:
    >
    >> I agree it's unlikely, but the possibility is no doubt the reason for
    >> NSRectToCGRect() existing (it uses the union trick).
    >
    > I think that means that NSRectToCGRect() must take care to be
    > compiled with the correct setting of -fstrict-aliasing.
    >
    >> Could you not make your Graphics::Rect class Objective-C++?  Just
    >> changing its extension should do the trick.
    >
    > Perhaps, but it would limit its usefulness. All files that included
    > the header file would need to use .mm as an extension.

    Not really:

    MyRect.h:

    class Rect {
    public:
    Rect(CGRect rect);
    #ifdef __OBJC__
    Rect(NSRect rect);
    #endif
    Rect(float left, float top, float right, float bottom);
    }

    MyRect.mm:

    Rect::Rect(CGRect rect) {
    }

    Rect::Rect(NSRect rect) {
    }

    ...

    Any ".mm" file that includes MyRect.h will be able to use the NSRect
    version, a ".cp" file wont (nor should it be able to, since it would
    need to be Objective-C++ to have seen an NSRect in the first place)

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium | prime : build, mutate, evolve, animate : the next
    generation of fractal art
  • The implementation should be okay with or without with -fstrict-aliasing.

    Pointer casting still works too, it's just ugly and screws up type
    checking (and violates strict aliasing).  NSRectToCGRect and friends
    were added as convenience.

    Struct tags also show up in objective-c method signatures, which are
    introspectable and in @encode directives, which are evaluated to c
    strings at compile time.  Code that wants to treat  NSRect, NSPoint
    and NSSize specially (e.g. KVC's object wrapping of those return
    types) tends to require a recompile when struct tags in the method
    signatures change.  Obviously KVC itself isn't a problem, since it
    ships in sync with the NSGeometry header, but external clients can
    (and do) have similar dependencies.

    The difference between long and int is also introspectable in method signatures.

    Ken Ferry
    Cocoa Frameworks

    On Dec 17, 2007 1:11 PM, Rick Mann <rmann...> wrote:
    >
    > On Dec 17, 2007, at 1:04 PM, Sean McBride wrote:
    >
    >> I agree it's unlikely, but the possibility is no doubt the reason for
    >> NSRectToCGRect() existing (it uses the union trick).
    >
    > I think that means that NSRectToCGRect() must take care to be compiled
    > with the correct setting of -fstrict-aliasing.
    >
    >> Could you not make your Graphics::Rect class Objective-C++?  Just
    >> changing its extension should do the trick.
    >
    > Perhaps, but it would limit its usefulness. All files that included
    > the header file would need to use .mm as an extension.
    >
    > --
    > Rick
    >
  • Indeed, the C standard guarantees that structures with the same
    initial sequence of members are layer out identically (at least as far
    as those initial members are concerned)

    Clark Cox III
    <Clark.cox...>
    Sent from my iPhone

    On Dec 17, 2007, at 14:52, Rick Mann <rmann...> wrote:

    >
    > On Dec 17, 2007, at 9:48 AM, Sean McBride wrote:
    >
    >> Yes, but nothing stops the compiler from padding or aligning CGRect
    >> differently from NSRect.  Of course, it's unlikely, but possible.
    >> See '-
    >> fstrict-aliasing' in the gcc man page.
    >
    > It seems unlikely to me that the two structs would ever be treated
    > differently by the compiler. I suppose an Objective-C compiler might
    > treat it differently than C++, but for the Mac OS APIs that use
    > NSRect to be built differently than client code that use NSRect,
    > well, that would be unacceptable. The only other difference between
    > them, then, is the name of the struct, which also would be an
    > unacceptable influence on the actual layout of the struct.
    >
    > The more serious problem is that the C++ compiler cannot include the
    > file defining NSRect; it contains Objective-C code. So, I can't make
    > my Graphics::Rect class accept NSRects at all. It would be great if
    > Apple could move NSRect to CGGeometry.h. Sigh.
    >
    > --
    > Rick
    >
previous month december 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
Go to today