Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

GothicChess.Com

macrumors regular
Original poster
Apr 6, 2007
126
0
Philadelphia, PA
As a result of this thread, Carbon vs. Cocoa, a structered debate : https://forums.macrumors.com/threads/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.
 

iSee

macrumors 68040
Oct 25, 2004
3,539
272
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.
 

GothicChess.Com

macrumors regular
Original poster
Apr 6, 2007
126
0
Philadelphia, PA
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?
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
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 :)
 

GothicChess.Com

macrumors regular
Original poster
Apr 6, 2007
126
0
Philadelphia, PA
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 :)

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 :)
 

Fukui

macrumors 68000
Jul 19, 2002
1,630
18
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...


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?

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.....
 

garethlewis2

macrumors 6502
Dec 6, 2006
277
1
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.
 

cblackburn

macrumors regular
Jul 5, 2005
158
0
London, UK
Code:
void solve_3_checkers_versus_3_checkers(void)
{
     ...
}

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
 

lazydog

macrumors 6502a
Sep 3, 2005
709
6
Cramlington, UK
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.

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
 

GothicChess.Com

macrumors regular
Original poster
Apr 6, 2007
126
0
Philadelphia, PA
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

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.
 

garethlewis2

macrumors 6502
Dec 6, 2006
277
1
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++.
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
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.

Hm, not sure if I can comment on this in more detail, but I think you are incorrect.
 

Fukui

macrumors 68000
Jul 19, 2002
1,630
18
Hm, not sure if I can comment on this in more detail, but I think you are incorrect.

Yea, thats under NDA, probably... I wouldn't put too much weight behind assertions about things that haven't been publicly stated by apple.
 

GothicChess.Com

macrumors regular
Original poster
Apr 6, 2007
126
0
Philadelphia, PA
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.
 

garethlewis2

macrumors 6502
Dec 6, 2006
277
1
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.
 

HiRez

macrumors 603
Jan 6, 2004
6,250
2,576
Western US
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.
 

Nutter

macrumors 6502
Mar 31, 2005
432
0
London, England
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.
 

GeeYouEye

macrumors 68000
Dec 9, 2001
1,669
10
State of Denial
Hm, not sure if I can comment on this in more detail, but I think you are incorrect.

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.
 

garethlewis2

macrumors 6502
Dec 6, 2006
277
1
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.
 

SC68Cal

macrumors 68000
Feb 23, 2006
1,642
0
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 :)
 

GeeYouEye

macrumors 68000
Dec 9, 2001
1,669
10
State of Denial
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.

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.

Catfish_Man said:
Making sure it's not on the stack?
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.
 

GothicChess.Com

macrumors regular
Original poster
Apr 6, 2007
126
0
Philadelphia, PA
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.

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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.