Cocoa Topics for Carbon Ex-patriots

Discussion in 'Mac Programming' started by GothicChess.Com, Jun 29, 2007.

  1. macrumors regular

    GothicChess.Com

    Joined:
    Apr 6, 2007
    Location:
    Philadelphia, PA
    #1
    As a result of this thread, Carbon vs. Cocoa, a structered debate : http://forums.macrumors.com/showthread.php?t=317580

    ...I have decided to begin my Cocoa development phase sooner rather than later. My former initial objective was to take my OS 9 apps to Carbon to at least have them running native under OS X. I will continue what I have started for the sake of feeling some form of accomplishment, but all of my new projects will be with Cocoa.

    Thanks to all who helped me make up my mind :) While I felt some of the discussion was needlessly overheated at times, it did address some key points, and for those who stayed on topic, my thanks.

    I'd like to open up a new thread wherein the "Cocoa way" to do things that the Carbon-minded might find useful. I'll try to come up with some "common denominator" code snippets, not just items overly-specific to some of the 2,000,000 lines of code I have going back to the days of CodeWarrior and MPW.

    I'll start things off in my next post, thank again to all of the Cocoa diehards out there.
     
  2. macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #2
    LOL!!! :D I read a bunch of that thread (until it got ridiculous)...

    Anyway, I'm a Carbon expat, too (although the process came much easier to me), so I'm interested to see what this leads to.
     
  3. thread starter macrumors regular

    GothicChess.Com

    Joined:
    Apr 6, 2007
    Location:
    Philadelphia, PA
    #3
    Writing to disk without using "Standard File"

    One of the things I have done in C under carbon has been the writing of very large files for use with my chess, checkers, and Gothic Chess programs (see http://www.GothicChess.com if you want to see a cool version of chess with more pieces on the board.)

    The files are basically millions or billions of positions with information such as "mate in 141" associated with each one.

    A sample of how the data is written to disk...

    Code:
    void solve_3_checkers_versus_3_checkers(void)
    {
         unsigned char *g_db6_0K3C_0K3C = NULL;
    
         FILE *file_pointer;
         unsigned long k_how_many_positions = 7959904;
         unsigned long i;
    
         g_db6_0K3C_0K3C = (unsigned char *)malloc(k_how_many_positions);
         if(g_db6_0K3C_0K3C) 
         {
             /* initialize the values to highest 8-bit value */
              for(i = 0; i < k_how_many_positions; i++)
                   g_db6_0K3C_0K3C[i] = 255;
         
    
         /* some code to solve all of the positions goes here... */
    
         file_pointer = fopen("db_06_(0K3C_0K3C)","wb");
         fwrite(g_db6_0K3C_0K3C, k_how_many_positions, 1, file_pointer);
         fclose(file_pointer);
         free(g_db6_0K3C_0K3C);
         }
    }
    
    Now, the vast majority of what you read and write is done after displaying the standard file dialog box. In the case above, this is completely circumvented because the "solving" of the data takes a while, and it just needs to be dumped from the RAM buffer to disk.

    My question is: Does Cocoa require you to interact with the "Standard File" dialogs, or can you write directly to disk as in the above example?

    How would one write the aforementioned using Cocoa?
     
  4. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #4
    Well, if you're doing a pure Cocoa app, you'd have a lot of NSObjects and inside them NSStrings and NSDatas, with both have writeToFile:atomically: methods. Very easy :)
     
  5. thread starter macrumors regular

    GothicChess.Com

    Joined:
    Apr 6, 2007
    Location:
    Philadelphia, PA
    #5
    That is encouraging :)

    What is going to be very cool is when the databases being solved require gigantic chunks of RAM to solve quickly, such as the 3 kings + 2 checkers versus 3 kings + 2 checkers database, which has 946,853,107,200 (946 billion) positions!

    I would still like to see how the code snippet in my previous post would look completely ported to Cocoa. I need to "see an example" to crib my way over to the Cocoa world :)
     
  6. macrumors 68000

    Fukui

    Joined:
    Jul 19, 2002
    #6
    You can do what ever you want. Cocoa is just an infrastructure, use pure C for your file writing if you want. As always, test, and if there are advantages to using NSData etc. then try it and test, see what your performance is... one thing about using a lot of C is though, unicode. Using the Cocoa API's you get internationalization for free..... again, it depends on what your saving.....
     
  7. macrumors 6502

    Joined:
    Dec 6, 2006
    #7
    Have you bought the books from the Big Nerd Ranch?

    As iterated by another poster, you can do anything you want with Cocoa. You can't write the GUI code in C, but unless your code is so tightly coupled you can call functions directly in Objective-C. You might want to wait for Leopard before starting development. Besides GC which is run in a parallel thread, no NDA issues there. The [] convention for Objective-C is going to be added to with .

    In other words

    Fraction *fract = [[[Fraction] initWithNum: 1 over: 3] autorelease]

    Could be written as

    Fraction *fract = Fraction.initWithNum(1,3).autorelease;

    Makes it easier for Java and C++ developers to get their heads around.
     
  8. macrumors regular

    Joined:
    Jul 5, 2005
    Location:
    London, UK
    #8
    If I was coding that in Cocoa I would use the code you just pasted :). None of that code segment contains Carbon calls, it's all raw POSIX C. This will become 64 bit in leopard and be supported for years to come.

    More than that this code is battle hardened and proven to be stable by you. Also Cocoa is a very nice framework to code in but no one can argue against the fact that it is always slower than the Raw C alternative.

    To move your app from Carbon to Cocoa you need only change the Carbon GUI calls to Cocoa GUI calls, all the Raw C code you have just copy and paste.

    Chris
     
  9. macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #9
    Fantastic! I was just thinking a couple of nights ago if it would be possible to convert the bracketed format to dot format.

    I have one question though, in your example would the call not be

    Fraction *fract = Fraction.initWithNumOver(1,3).autorelease;


    Thanks for the post, I look forward to the Leopard release even more now.

    b e n
     
  10. thread starter macrumors regular

    GothicChess.Com

    Joined:
    Apr 6, 2007
    Location:
    Philadelphia, PA
    #10
    I was kind of wishing along these lines :)

    I didn't know if Cocoa would put a stop to the C file I/O such as fopen() and fwrite(), forcing some XML format enveloped inside calls to the Standard File dialog boxes.

    I would say 90% of my code, possibly even more, is highly optimized C code, so it sounds like the jump to Cocoa might not be too bad at all.
     
  11. macrumors 6502

    Joined:
    Dec 6, 2006
    #11
    If your code isn't tightly coupled at all, then you should have no problems converting from Carbon calls to Cocoa.

    You seem to have your head filled with horror stories stating that Cocoa forces you to open files using NSHugeCrapRubbishMethod that takes 8 hours to run. These are convenience methods designed to make it easier to code, they aren't slow, as they wrap around the raw IO calls from Posix.

    Just please don't fall into the trap of believing that dynamic dispatch is massively slow compared to static method binding. If it was, Apple would never have coded OS X with Objective-C. They would have converted the entire framework of NextSTEP over to C++.
     
  12. thread starter macrumors regular

    GothicChess.Com

    Joined:
    Apr 6, 2007
    Location:
    Philadelphia, PA
    #12
    It's up to 8 now? It was just 7.5 last week!

    :)
     
  13. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #13
    Hm, not sure if I can comment on this in more detail, but I think you are incorrect.
     
  14. macrumors 68000

    Fukui

    Joined:
    Jul 19, 2002
    #14
    Yea, thats under NDA, probably... I wouldn't put too much weight behind assertions about things that haven't been publicly stated by apple.
     
  15. thread starter macrumors regular

    GothicChess.Com

    Joined:
    Apr 6, 2007
    Location:
    Philadelphia, PA
    #15
    So has anyone written a Cocoa App that...

    I am wondering if there is an OpenSource example of an application that handles all of the standard events in Cocoa...

    Menus, windows with drawers, the old "offscreenbitmaps" kind of color animation, tracking for the replacement to the old "keyDown" event, opening/saving of files, stuff like that.

    I would like to stratify by #define some of the OS-dependent stuff. For example, I have a cool blackjack program that I can run under OS 9 on a 680X0 Mac, a Power Mac, and now under OS X as a Carbonized app, all by changing one #define. Technically speaking, I can even run it under OS 6.0.5 which was the last stable release before "System 7", but the code is not as clean as it should be.

    I would eventually like to make a Cocoa app that can be run under any Macintosh, just for kicks :)

    If anyone knows of some good OpenSource Cocoa links, feel free to post them here.
     
  16. macrumors 6502

    Joined:
    Dec 6, 2006
    #16
    No it's not under NDA.

    It is part of the new GCC features for Objective-C 2.0. Whether Apple adopts them is not known, but they are part of gcc now.
     
  17. macrumors 601

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #17
    If you use Objective-C seriously for a week or so and still can't "get your head around" the bracketed format, then you probably never will (meaning, you're not a very adaptable programmer). I came from a Java background, it was weird for me for a few days, but that's it. Now I love it, and Cocoa's wordy method names and self-documenting, forced named message arguments. I've certainly come to see Objective-C code as more readable than Java, C, C++, Perl, PHP, and other languages (still love looking at Python code though). Having said that, I am looking forward to abbreviated enumeration/loop handling.
     
  18. macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #18
    Cocoa / Carbon with #define? Not bloody likely!

    The philosophy of Cocoa is entirely different to Carbon. There's no one-to-one mapping of functionality from one to the other. While Objective-C is a superset of C, Cocoa itself takes full advantage of the dynamic object-oriented features of the language. That's what makes Cocoa such a successful and unique API. Trying to hack it onto your existing C implementation is a bit of a waste of time, and much more difficult than putting your C code in Objective-C wrapper classes that can be used properly with Cocoa.

    I mean, really, in 2001 I could understand the appeal of supporting both OS 9 and OS X with one source. But supporting OS 6? Today, in 2007? For fun??! Weird.
     
  19. macrumors 68000

    GeeYouEye

    Joined:
    Dec 9, 2001
    Location:
    State of Denial
    #19
    You can, as it's all in the GCC repository, and he is incorrect. What he posted is only true for getters and setters, and only if an ivar is declared as a property.

    As for the original question, I'd transform the code into a method on the application controller class:

    Code:
    /* In AppController.m */
    -(void)solve_3_checkers_versus_3_checkers
    {
         unsigned char *g_db6_0K3C_0K3C = NULL; 
         NSString *fileName = @"db_06_(0K3C_0K3C)"
         unsigned long k_how_many_positions = 7959904;
         unsigned long i;
    
         g_db6_0K3C_0K3C = (unsigned char *)malloc(k_how_many_positions);
         if(NULL != g_db6_0K3C_0K3C) 
         {
             /* initialize the values to highest 8-bit value */
              for(i = 0; i < k_how_many_positions; i++)
                   g_db6_0K3C_0K3C[i] = 255;
         
    
         /* some code to solve all of the positions goes here... */
         NSData *fileData = [NSData dataWithBytes:g_db6_OK3C_0K3C];
         [fileData writeToFile:fileName atomically:YES];
         free(g_db6_0K3C_0K3C);
         }
    }
    You'll notice I declared an NSData * midway through - I just leave C99 enabled. You can move the declaration to the top of the block if you have to use C89 for some reason.

    Also, I'm a bit confused as to why you need to malloc instead of simply declaring g_db6_0K3C_0K3C as an array of k_how_many_positions unsigned chars.
     
  20. macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #20
    Making sure it's not on the stack?
     
  21. macrumors 6502

    Joined:
    Dec 6, 2006
    #21
    Who said it was in the repository for GCC.

    If you think Apple would put those features into the public domain before releasing Leopard you are smoking too much pot.
     
  22. macrumors 68000

    Joined:
    Feb 23, 2006
    #22
    Gothic,

    How much of your code is similar to the snippets above? You might already be a step ahead of the game if most of your engine is POSIX C code. You might just be doing GUI work :)
     
  23. macrumors 68040

    MongoTheGeek

    Joined:
    Sep 13, 2003
    Location:
    Its not so much where you are as when you are.
    #23
    A bunch of the iCal stuff is in the wild and actually more advanced than what is in the leopard beta. Then again thats in the nightly builds.
     
  24. macrumors 68000

    GeeYouEye

    Joined:
    Dec 9, 2001
    Location:
    State of Denial
    #24
    The Objc-lang mailing list run by Apple disagrees. There have been dozens of discussion threads about what's in Objective-C 2.0, and Apple monitors (and occasionally posts) on that list. It's Cocoa in Leopard that's not allowed to be talked about, except for what's already known.

    Well yeah, but why? It's not being returned, and if it's likely to overflow the remaining stack space and hit the heap, it'd overflow the remaining heap space and hit the stack if it's allocated there.
     
  25. thread starter macrumors regular

    GothicChess.Com

    Joined:
    Apr 6, 2007
    Location:
    Philadelphia, PA
    #25
    Thanks for that code conversion... starting to get the feel for this newer stuff now.

    The short answer to your question: During part of the computation, I can stuff 4 checkers positions into each byte. The positions have values of either UNKNOWN, WIN, LOSS, or DRAW. I use binary 11 for UNKNOWN, 10 for WIN, 01 for DRAW, and 00 for LOSS.

    Using only 2-bits per position, I can line 4 of them up in one byte.

    So say I need to know what is the value of position #105671.

    I know it is in byte # (105671/4) = 26417. So g_db6_0K3C_0K3C[26417] is the byte with the result. Since (105671%4) = 3, I know the result is in bits (3 x 2) + 1 and (3 x 2) + 2 = 7 and 8.

    With a bit pattern such as 11000000 representing the mask for bits 7 and 8 being set, I can say:

    my_result = g_db6_0K3C_0K3C[26417] & 0xC0; where the result will be WIN, LOSS, DRAW, or UNKNOWN.

    This may seem like a waste of time, until you try and solve the 132 billion positions comprising every 8-piece (and fewer) combination possible in the game of checkers.

    During another phase of the computation, I filter out all of the draws, and only "operate" on the WINS and LOSS values. During that phase, I realloc() and need 1 byte per position, using all 8-bits to describe the distance to win (or lose.) But, since maybe 35% of the positions are draws, they drop out, saving RAM, and loop iteration time.
     

Share This Page