Professional Web Applications Themes

legacy code in cocoa obj C? - Mac Programming

hi, i'm new to OOP and cocoa but am familiar with procedural C, functions, structures and pointers... etc. just when cocoa was starting to sink in i run into this.... this is SG DataProc sample code from apples quicktime developer site. (condensed version!) #<import statements> interface myquickdrawview : NSQuickDrawView { // instance variables here } -(...); // method declarations here end // all seems straightfoward enough but, // below is what stumps me... pascal OSErr mySGDataProc (SGChannel c, ptr p, long len.... etc); void saveQDViewObjectforcallback(void *theObject); -what is that pascal statement doing in there?! what does it do? -is it ...

  1. #1

    Default legacy code in cocoa obj C?

    hi, i'm new to OOP and cocoa but am familiar with procedural C,
    functions, structures and pointers... etc.
    just when cocoa was starting to sink in i run into this....
    this is SG DataProc sample code from apples quicktime developer site.
    (condensed version!)

    #<import statements>
    interface myquickdrawview : NSQuickDrawView
    {
    // instance variables here
    }
    -(...); // method declarations here
    end // all seems straightfoward enough but,
    // below is what stumps me...

    pascal OSErr mySGDataProc (SGChannel c, ptr p, long len.... etc);
    void saveQDViewObjectforcallback(void *theObject);


    -what is that pascal statement doing in there?! what does it do?
    -is it some type of struct?
    -how are these two lines treated and dealt with when they arent
    contained within the interface-end statement?!? is this a common
    practice in cocoa?

    help is greatly appreciated!
    thanks!
    Jeff Guest

  2. #2

    Default Re: legacy code in cocoa obj C?

    In article <google.com>,
    com (Jeff Leary) wrote:
     

    'pascal' is a legacy keyword that has no effect now. It's from the era
    of 68k machines and a Mac System that was written in Pascal. On the 68k,
    Pascal and C had different function calling conventions. (IIRC, they
    passed arguments in the opposite order.) Since the system used Pascal,
    if you programmed in C and registered a C function with the OS, you used
    the 'pascal' keyword to indicate that this function should use Pascal
    calling conventions.
     

    interface and end only affect the OO parts of ObjC, they don't affect
    C things at all. Everything in ObjC that's C can be treated just like it
    was really C, because that's all it is. ObjC is a very, very thin OO
    wrapper around normal C. So these are normal C function prototypes.
    Being inside or outside the interface-end section will have no effect
    on them.

    They're here because you're accessing QuickTime, which has no ObjC API.
    It's all C, so you need C functions in order to use it.
    Michael Guest

  3. #3

    Default Re: legacy code in cocoa obj C?

    dans l'article mail-C8D5A5.22513521102003localhost, Michael Ash à
    com a écrit le 21/10/03 22:51:
     

    'pascal' is STILL a legacy keyword, and it DOES have effect. For example, if
    you provide an ICMProgressProc to GraphicsImportSetProgressProc, you need to
    pass a UPP which in turn will call your proc using pascal conventions.

    This has nothing to do with 68K, it has to do with the fact that the MacOS
    API was initially written in pascal, not in C. Since the system software
    does not know which programming language you're using, you MUST follow these
    conventions.

    You meet the same conventions on Windows, except they have different names:
    pascal is called __stdcall, and C is __cdecl, there are also other
    conventions for assembly and so on.

    Regards,

    Eric.

    Eric Guest

  4. #4

    Default Re: legacy code in cocoa obj C?

    In article <BBBB6D89.14297%fr>,
    Eric VERGNAUD <fr> wrote:
     

    My understanding is that, on PPC, Pascal and C calling conventions are
    identical. So 'pascal' has no effect other than shutting up the compiler
    when it tells you you don't have the right type. Not to say that it's
    safe to leave it out or anything.... If this is wrong, I would be happy
    to be corrected.
    Michael Guest

  5. #5

    Default Re: legacy code in cocoa obj C?

    In article <mail-C8D5A5.22513521102003localhost>, Michael Ash
    <com> wrote:
     

    Just to nitpick, it's from the era of 68K machines and System Software
    with Pascal calling conventions. I wouldn't assume from the calling
    conventions anything about the actual implementation of the System
    Software.

    -- Chris

    --
    Chris Hanson, bDistributed.com, Inc. | Email: com
    Custom Application Development | Phone: +1-847-372-3955
    http://bdistributed.com/ | Fax: +1-847-589-3738
    http://bdistributed.com/Articles/ | Personal Email: com
    Chris Guest

  6. #6

    Default Re: legacy code in cocoa obj C?

    dans l'article mail-D7DB30.23343921102003localhost, Michael Ash à
    com a écrit le 21/10/03 23:34:
     
    >
    > My understanding is that, on PPC, Pascal and C calling conventions are
    > identical.[/ref]

    No, they're not.
     

    It is. Try casting a C function into a pascal function and passing it as a
    callback to a system function that expects a pascal call. You'll probably
    crash, but even if you don't, you'll find that arguments are passed in
    reverse order.

    This also has some effects when linking libraries. A pascal function is
    typycally named _MyFunction. A C function will be named MyFunction. A C++
    function will be named... è§&è§èé§(MyFunctionç&ç!y or something of the
    kind (not standard since there is no standard for C++ naming conventions).
    All this naming stuff reflects that the calling conventions still differ,
    whether the underlying processor is PPC or 68K.

    Eric

    Eric Guest

  7. #7

    Default Re: legacy code in cocoa obj C?

    In article <BBBC3A5B.142FD%fr>,
    Eric VERGNAUD <fr> wrote:
     
    > >
    > > My understanding is that, on PPC, Pascal and C calling conventions are
    > > identical.[/ref]
    >
    > No, they're not.

    >
    > It is. Try casting a C function into a pascal function and passing it as a
    > callback to a system function that expects a pascal call. You'll probably
    > crash, but even if you don't, you'll find that arguments are passed in
    > reverse order.[/ref]

    According to this page, calling conventions for all languages are the
    same on PPC:

    http://developer.apple.com/doentation/mac/PPCSoftware/PPCSoftware-15.h
    tml
    (Look about halfway down the page, under "Calling Conventions".)

    There are probably cases and languages where this is not true, but the
    page specifically mentions Pascal and C. Everything I have been able to
    find indicates that the conventions were different on 68k (such as
    passing parameters in reverse order), but that this is not the case on
    PPC.
     

    This doesn't really matter for this discussion, since we're talking
    about registering callbacks. But I would be surprised if this were true.
    Not terribly surprised, though.
     

    Every exported C function i have seen has been named with a leading
    underscore, like _MyFunction. Are these two examples backwards?
     

    C++ function name mangling has nothing to do with C++ calling
    conventions. It only exists to support C++ function overloading, where
    multiple functions with the same name but taking different numbers or
    types of parameters can exist in the same file. The function names are
    mangled to reflect the types they take so that they don't conflict with
    each other. But they still have the same calling conventions once you
    get the right name.
    Michael Guest

  8. #8

    Default Re: legacy code in cocoa obj C?

    > According to this page, calling conventions for all languages are the 

    Interesting. I made a test with non-system calls and the pascal directive
    has indeed no effect.

    However, remember that prior to MacOS X, PowerPC Macs were able to execute
    68k code. This is one of the reasons you had to provide a UPP to system
    functions taking a function pointer as parameter. So my guess is that this
    is still required for MacOS9/Classic, since the system is calling the
    callbacks using 68k calling conventions.

    Eric


    Eric Guest

  9. #9

    Default Re: legacy code in cocoa obj C?

    Hi Michael,


    Michael Ash <com> writes: 

    <nitpicking>

    Make that "they usually (with most compilers) still have the same
    calling conventions". If you want to be sure and portable, you need
    to use 'extern "C"'.

    IOW, 'extern "<language>"' can change the calling conventions used.
    And C and C++ are allowed to differ on calling conventions.

    </nitpicking>


    benny
    Benjamin Guest

  10. #10

    Default Re: legacy code in cocoa obj C?

    In article <benny.turtle-trading.net>,
    Benjamin Riefenstahl <de> wrote:
     
    >
    > <nitpicking>
    >
    > Make that "they usually (with most compilers) still have the same
    > calling conventions". If you want to be sure and portable, you need
    > to use 'extern "C"'.
    >
    > IOW, 'extern "<language>"' can change the calling conventions used.
    > And C and C++ are allowed to differ on calling conventions.
    >
    > </nitpicking>[/ref]

    So this means that it is technically unsafe to pass a C++ function as a
    callback to OS code or a C library, unless that function is declared as
    extern "C"? And passing a static method must be right out, too.
    Michael Guest

  11. #11

    Default Re: legacy code in cocoa obj C?

    In article <BBBC491D.1430C%fr>,
    Eric VERGNAUD <fr> wrote:
     
    >
    > Interesting. I made a test with non-system calls and the pascal directive
    > has indeed no effect.
    >
    > However, remember that prior to MacOS X, PowerPC Macs were able to execute
    > 68k code. This is one of the reasons you had to provide a UPP to system
    > functions taking a function pointer as parameter. So my guess is that this
    > is still required for MacOS9/Classic, since the system is calling the
    > callbacks using 68k calling conventions.[/ref]

    This doesn't make any sense. A UPP translates between different calling
    conventions as it is, to translate between 68k and PPC. It will, of
    course, translate to/from 68k Pascal calling conventions when necessary.
    If PPC calling conventions are the same, they're the same. If you're
    writing 68k code, then it's certainly required, otherwise it's
    "required" in the sense that you really ought to put it there even if it
    has no effect, just to future-proof your code.
    Michael Guest

  12. #12

    Default Re: legacy code in cocoa obj C?

    dans l'article mail-FD1C8A.16150522102003localhost, Michael Ash à
    com a écrit le 22/10/03 16:15:
     
    >>
    >> Interesting. I made a test with non-system calls and the pascal directive
    >> has indeed no effect.
    >>
    >> However, remember that prior to MacOS X, PowerPC Macs were able to execute
    >> 68k code. This is one of the reasons you had to provide a UPP to system
    >> functions taking a function pointer as parameter. So my guess is that this
    >> is still required for MacOS9/Classic, since the system is calling the
    >> callbacks using 68k calling conventions.[/ref]
    >
    > This doesn't make any sense. A UPP translates between different calling
    > conventions as it is, to translate between 68k and PPC. It will, of
    > course, translate to/from 68k Pascal calling conventions when necessary.
    > If PPC calling conventions are the same, they're the same. If you're
    > writing 68k code, then it's certainly required, otherwise it's
    > "required" in the sense that you really ought to put it there even if it
    > has no effect, just to future-proof your code.[/ref]

    Maybe I wasn't clear enough: what could be required is the pascal keyword in
    the system callback prototype (so the UPP is properly built), not in the
    implementation.

    It's safer anyway to have a callback conform to the prototype, it avoids
    casting it, which could hide other differences:

    Example:
    typedef pascal void (*MyCallback)(long,long);

    void MyWrongCallback_C(); // prototype is wrong
    pascal void MyWrongCallback_P(); // prototype is wrong

    // the following line will compile, but will crash
    MyCallback cb = (OsCallback)MyWrongCallback_C; // casting hides error

    // the following line will not compile
    MyCallback cb = MyWrongCallback_P; // type checked by the compiler

    Regards,

    Eric


    Eric Guest

  13. #13

    Default Re: legacy code in cocoa obj C?

    > So this means that it is technically unsafe to pass a C++ function as a 

    You can pass a static function ok, I do it all the time, or a C++ global
    method. However you cannot pass a C++ member function, because when the
    callback is called, the 'this' implicit parameter would not be properly
    initialized.

    Also, since there is no standard name mangling mechanism, there is no way to
    guarantee that an exported C++ static or global function will be found by
    another software. You must use extern "C" to ensure that the exported name
    will conform to the standard.

    Eric

    Eric Guest

  14. #14

    Default Re: legacy code in cocoa obj C?

    Hi Michael,

     [/ref]

    Michael Ash <com> writes: 

    Yes, I think so. "Technically" is of course an important bit here, a
    compiler would be stupid to actually do this, especially on a platform
    where this kind of code is already common practice. But a compiler
    could (should IMO) throw a warning for using C++ functions as C
    function pointers without 'extern "C"'.
     

    Yes. If you don't want ot use global functions, you can use file
    local static functions in an 'extern "C"' block:

    extern "C" {
    static int blubcallback(void * clientdata) {
    return static_cast<YourClass*>(clientdata)->blub();
    }
    }

    That may look curious, but it is correct code and accepted by all
    compilers with which I have tested it here.


    benny
    Benjamin Guest

  15. #15

    Default Re: legacy code in cocoa obj C?

    In article <benny.turtle-trading.net>,
    Benjamin Riefenstahl <de> wrote:
     
    >
    > Yes, I think so. "Technically" is of course an important bit here, a
    > compiler would be stupid to actually do this, especially on a platform
    > where this kind of code is already common practice. But a compiler
    > could (should IMO) throw a warning for using C++ functions as C
    > function pointers without 'extern "C"'.[/ref]
    [other good stuff snipped]

    Thanks for the info, it's interesting and good to know.
    Michael Guest

  16. #16

    Default Re: legacy code in cocoa obj C?

    In article <mail-C8D5A5.22513521102003localhost>,
    Michael Ash <com> wrote: 

    The same used to be the case when programming 16 bit Windows - callback
    functions associated with message processing had to be compiled with
    PASCAL calling conventions. Who knows what the reasoning was; C was
    the original programming language for the Windows SDK - Borland's Turbo
    Pascal came later. There may be some efficiency benefits, perhaps.

    Tim

    Tim Guest

  17. #17

    Default Re: legacy code in cocoa obj C?

    In article <mail-FD1C8A.16150522102003localhost>,
    Michael Ash <com> wrote:
     
    >
    > This doesn't make any sense. A UPP translates between different calling
    > conventions as it is, to translate between 68k and PPC.[/ref]

    To pick another nit in this thread, a UPP doesn't translate anything. It
    specifies.

    G
    Gregory Guest

  18. #18

    Default Re: legacy code in cocoa obj C?

    In article <BBBC66AE.1434F%fr>,
    Eric VERGNAUD <fr> wrote:
     
    >
    > You can pass a static function ok, I do it all the time, or a C++ global
    > method. However you cannot pass a C++ member function, because when the
    > callback is called, the 'this' implicit parameter would not be properly
    > initialized.[/ref]

    The question is not whether you do it all the time, nor whether if you do it
    works. The question is whether the C++ standard guarantees the desired behavior,
    and the current answer (as quoted above) is that it doesn't.

    meeroh

    --
    If this message helped you, consider buying an item
    from my wish list: <http://web.meeroh.org/wishlist>

    Miro Guest

  19. #19

    Default Re: legacy code in cocoa obj C?

    dans l'article mit.edu, Miro
    Jurisic à org a écrit le 23/10/03 5:24:
     
    >>
    >> You can pass a static function ok, I do it all the time, or a C++ global
    >> method. However you cannot pass a C++ member function, because when the
    >> callback is called, the 'this' implicit parameter would not be properly
    >> initialized.[/ref]
    >
    > The question is not whether you do it all the time, nor whether if you do it
    > works. The question is whether the C++ standard guarantees the desired
    > behavior,
    > and the current answer (as quoted above) is that it doesn't.
    >[/ref]

    Sorry to insist, but the question was not whether this is part of the
    standard, but whether it is technically safe.

    I said it was, but I shouldn't be so general. This is compiler dependant,
    but since the naming scheme is not involved, I say you can safely rely on
    the compiler's type checking (which IS part of the C++ standard). If you
    write:

    void (*MyProcPtr)(long);

    public class A {
    public static void MyProc(long);
    };

    MyProcPtr procptr = A::MyProc;

    Provided the compiler doesn't throw any error or warning, you can say it is
    100% safe.

    In the above example, using a C function with a pascal prototype, or a
    member function with a C prototype does generate compiler errors with all
    compilers I know (CW, GCC, VC++), but doesn't with the example, which shows
    that the compiler performs strong type checking on function pointers in
    order to guarantee that the function complies with the expected calling
    conventions.

    However I agree that this is not in the standard, and that it may not be
    portable. So I would say this is generally safe (since most C++ compilers
    produce C-compliant code), but needs to be validated with each compiler.

    Obviously, using a flat C function in place of a static class function is
    guaranteed to be portable. However, there are many advantages in using a
    static class function, which has access to protected and private members. So
    I think it is worth taking the time to validate the above with each
    compiler.

    Regards,

    Eric

    Eric Guest

  20. #20

    Default Re: legacy code in cocoa obj C?

    In article <mail-D7DB30.23343921102003localhost>,
    Michael Ash <com> wrote:
     

    I have a vague memory that the parameters for a Pascal call were
    stacked rather than being queued. So the effect of the word
    'pascal' in the call might be to reverse the parameter order
    in the call.


    Simon Guest

Page 1 of 2 12 LastLast

Similar Threads

  1. Legacy Migrations
    By darkharp in forum Coldfusion Server Administration
    Replies: 0
    Last Post: March 22nd, 05:50 AM
  2. Legacy saving
    By Joy_Hinckley@adobeforums.com in forum Adobe Illustrator Windows
    Replies: 5
    Last Post: July 1st, 11:44 PM
  3. Programmatically inserting controls into old legacy Response.Write style code
    By Benjamin Joldersma in forum ASP.NET Building Controls
    Replies: 0
    Last Post: May 13th, 06:41 PM
  4. Legacy Problem?
    By TYP3G1RL@adobeforums.com in forum Adobe Illustrator Macintosh
    Replies: 1
    Last Post: February 14th, 12:26 AM
  5. Legacy Parallel PCI
    By Bob Bailin in forum SCO
    Replies: 0
    Last Post: July 16th, 01:35 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139