Writing an ObcJ function/calling it from C++

Jones
Unregistered
 
Post: #1
Essentially, that's what I'd like to do. The function will be simple, it just needs to make a simple dialog box with one button (I still have to learn how to do this...). I already know how to do this with the Windows API, just not Cocoa because I never directly use it myself. I'd like to be able to call this function from C++ code too, although I know ObjC structures it's functions differently.

What if I wrote the ObjC function, and then made a #define func(args) type layer for the function, would that work?

(Perhaps this is a stupid question, but ObjC is so different from C and C++ it seems like they'd never work together. Thanks!)
Quote this message in a reply
Member
Posts: 257
Joined: 2004.06
Post: #2
Jones Wrote:(Perhaps this is a stupid question, but ObjC is so different from C and C++ it seems like they'd never work together. Thanks!)

Uh, actually, they do work together. Quite well, actually, and it's something I do a lot. If you're calling C/C++ code from another file, you can just call it (after including the header file or declaring it somehow in your Obj-C source file). Calling Obj-C code from C/C++ is a little trickier but it's doable. Poke around Apple's Developer website for sample code and documentation that talks about mixing Obj-C and C/C++.

The brains and fingers behind Malarkey Software (plus caretaker of the world's two brattiest felines).
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #3
If I may suggest, since you don't have much experience with Cocoa, why not just make a few programs out of nothing *but* Cocoa to really get your feet wet with it. That will make integration with other languages much easier to understand. Cocoa all by itself kicks major amounts of bootay. No, really, it does. Give it a try!
Quote this message in a reply
Member
Posts: 567
Joined: 2004.07
Post: #4
you could just use a simple carbon function... lemme find it...

oh yes, here it is.

Code:
#ifdef WIN32
#include <windows.h>
#elif defined __APPLE__
#include <Carbon/Carbon.h>
#endif

#include <cstdarg>
#include <iostream>
#include <sstream>

void ErrorMessage(const std::string &message);
void ErrorMessage(const std::string &message)
{
    #ifdef WIN32
        MessageBox(NULL, message.c_str(), "Error", MB_ICONERROR | MB_OK);
    #elif defined __APPLE__
        Str255 msg;
        c2pstrcpy(msg, message.c_str());
        StandardAlert(kAlertStopAlert, "\pError",
                             (ConstStr255Param)msg, NULL, NULL);
    #else
        std::cerr << "Error: " << error_text << std::endl;
    #endif
}

shouldn't be too hard to adapt it for your purposes. No use in creating a C/C++ wrapper for objc, when you can just use the native functions.

It's not magic, it's Ruby.
Quote this message in a reply
Jones
Unregistered
 
Post: #5
Nayr, that's *just* what I was looking for!

Thanks mate! Smile
Quote this message in a reply
Jones
Unregistered
 
Post: #6
Disaster strikes:

I ashamed to say that I can't even get this dialog to display correctly. LOL Rolleyes

One simple call of:
Code:
StandardAlert(    kAlertCautionAlert,
                        (const unsigned char*)title,
                        (const unsigned char*)message, NULL, NULL);

Causes an application crash with multiple errors, like:

Quote:2006-11-18 11:55:46.154 OpenGL[16185] *** _NSAutoreleaseNoPool(): Object 0x3711b0 of class NSCarbonWindowContentView autoreleased with no pool in place - just leaking
2006-11-18 11:55:46.177 OpenGL[16185] *** _NSAutoreleaseNoPool(): Object 0xa370d7d8 of class NSCFString autoreleased with no pool in place - just leaking
2006-11-18 11:55:46.208 OpenGL[16185] *** _NSAutoreleaseNoPool(): Object 0x374100 of class NSCFDictionary autoreleased with no pool in place - just leaking

But many more than just three... those look like Cocoa errors. Perhaps Carbon and Cocoa are duking it out? I was under the impression that GLUT used Carbon. Huh

Thanks!
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #7
GLUT is based on Cocoa on OS X -- because Cocoa kicks major bootay. Cocoa and Carbon work together just fine. It looks like you did some Cocoa stuff without first creating an NSAutoReleasePool.

[edit] You could do that like this:

NSAutoreleasePool *myAutoReleasePool = [[NSAutoreleasePool alloc] init];

// do Cocoa stuff

[myAutoReleasePool release];

[/edit]
Quote this message in a reply
Jones
Unregistered
 
Post: #8
*Becomes baffled by Cocoa code.* ZZZ

I think I've come up with another solution involving using a seperate executable. It sounds weird, but it's mainly for debugging purposes...

That code, BTW, would be much easier to use in an SDL app. I use GLUT apps when designing components and SDL when snapping them together for demonstrations, and later, games. It's a bit of a messy system, but it works for me. Smile
Quote this message in a reply
Member
Posts: 567
Joined: 2004.07
Post: #9
that code I gave you before will work in an sdl app. I'm not sure why it doesn't in your glut app...try it in SDL before giving up on it. That error will haunt you if you use cocoa, anyway.

It's not magic, it's Ruby.
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #10
Jones Wrote:*Becomes baffled by Cocoa code.* ZZZ
An NSAutoReleasePool is a really cool way to manage memory but it isn't an intuitive technique to grasp on first glance. It's essentially just a list of objects which you would like to have released when you release the pool. As you may know, Cocoa objects have the notion of a retain count. A retain count of zero means that the runtime should destroy the object. To set the object's retain count, you can retain, release, and autorelease. In short (really short), retain means add one to the retain count, release means subtract one from the retain count, and autorelease means subtract one from the retain count later -- typically at the end of the application's current execution cycle, when the release message is sent to the autorelease pool you created. Autorelease is handy because often times an object will initialize itself but has no interest in itself, but needs to make sure it stays around long enough for the object that called it in the first place to do something with it. Also, many objects are used in a transient fashion, such as an NSString used as an argument to another string for a moment. Calling release on objects like that all the time becomes redundant, so for convenience, many classes return autoreleased objects. If there isn't a list of autoreleases (an autoReleasePool) then there is no way to tell the runtime to release them and they become memory leaks.
Quote this message in a reply
Member
Posts: 567
Joined: 2004.07
Post: #11
ok, try this:
1. change your main function's file's extension to '.mm' from '.cpp', '.cxx', '.cc', '.C', etc.
2. add "#import <Foundation/Foundation.h>" to the beginning of your file.
3. add "NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];" to the first line of the main function.
4. add "[pool release];" to the last line before your return in the main function.
5. add the foundation framework to the project, if you're using xcode.
6. compile! it might work. Not sure why this should pop up in the first place; doesn't GLUT sue cocoa?

It's not magic, it's Ruby.
Quote this message in a reply
Jones
Unregistered
 
Post: #12
Nayr Wrote:ok, try this:
1. change your main function's file's extension to '.mm' from '.cpp', '.cxx', '.cc', '.C', etc.
2. add "#import <Foundation/Foundation.h>" to the beginning of your file.
3. add "NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];" to the first line of the main function.
4. add "[pool release];" to the last line before your return in the main function.
5. add the foundation framework to the project, if you're using xcode.
6. compile! it might work. Not sure why this should pop up in the first place; doesn't GLUT sue cocoa?

Somehow that sounds like the kind of solution Microsoft might use. It's quick, but it might break in the future. No offense, of course. Smile

Somehow telling xCode to compile a bunch of c++ dependent code as ObjC sounds like 2000 compiler errors. Annoyed
Quote this message in a reply
Member
Posts: 567
Joined: 2004.07
Post: #13
it's actually objective-c++. It should work fine; it IS a hack, though, only good to hold you over till you find the way you're supposed to do it.

It's not magic, it's Ruby.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #14
Write a header file like this:

Code:
#ifndef MyHeaderName_h
#define MyHeaderName_h

#if defined(__cplusplus)
extern "C" {
#endif

extern void myCFunctionPrototype(int arg0, const char *arg1, double arg2orWhatever);

#if defined(__cplusplus)
}
#endif

#endif

Now write an implementation file for that header:

Code:
#include "MyHeaderName.h"

void myCFunctionPrototype(int arg0, const char *arg1, double arg2orWhatever)
{
    // your code goes here
}

If you name that implementation file .c, you can write C code; if you name it .cc, .cpp, .cxx, etc. you can write C++ code; if you name it .m you can write ObjC code, if you name it .mm you can write ObjC++ code. You can include the header in files written in any of those languages, too.

This is the "old-fashioned" way of mixing C++ and ObjC, but it has the advantage that it keeps the code in the other language nice and isolated from the rest of your code.

Oh, and the NSAutoreleasePool messages are not the cause of your crashes; a fundamental lack of understanding of C vs. Pascal strings, combined with a cavalier attitude toward compiler errors and warnings, is the cause of your crashes.

Also, don't use StandardAlert; it's ancient, nasty, and deprecated. There are better ways of doing it (just say whether you want Cocoa or Carbon code).

And no, GLUT on Mac OS X does not use Carbon internally; it's implemented using Cocoa. You can download the source from Apple.
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #15
Jones Wrote:Somehow that sounds like the kind of solution Microsoft might use. It's quick, but it might break in the future. No offense, of course. Smile

Somehow telling xCode to compile a bunch of c++ dependent code as ObjC sounds like 2000 compiler errors. Annoyed

what on earth are you talking about, this is THE way to do it. Its a very clean and good solution.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Writing libraries vs writing apps. Najdorf 8 4,987 Nov 13, 2008 02:32 PM
Last Post: backslash
  Better way of calling a function in another class? brush 5 4,387 Jun 12, 2008 11:23 PM
Last Post: AnotherJake
  Problem drawing pictures after calling RunApplicationEventLoop petr6534 5 4,572 Feb 8, 2005 06:58 PM
Last Post: petr6534