Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
General
GeneralPortable MacsHardwareNetworking
Applications
Mac ApplicationsEudoraFirefox / MozillaInternet ExplorerOutlook ExpressMS OfficeEntourageExcelPowerPointWordVirtual PCMedia PlayerOther MS Products
Programming
Mac ProgrammingCodeWarriorPerl
Country Specific
Australian Mac GroupUK Mac Group

Mac Forum / Programming / Perl / October 2005



Tip: Looking for answers? Try searching our database.

Using Perl in Cocoa

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Manfred Bergmann - 27 Oct 2005 01:34 GMT
Hi there.

Er, I first had to find out that this is a mailing list and no  
newsgroup. I signed at google groups, posted messages and wondered  
why they actually are not there when I browsed the list at  
nntp.perl.org. At www.perl.org I actually figured that this is a  
list. Ohh dear.
So if the messages that I've send through google are arriving after  
all, i'd like to appologize just now. :)

I am almost new to Perl. I like it and tried to use it in some of my  
Cocoa Projects.

Just calling perl subroutines from C in't a problem with embedding a  
Perl Interpreter. But passing arguments from and to the perl script  
over pipe isn't what I want. If I could pass and get arguments or  
variables in a OO manner that would be great. If nothing else works,  
I probably have to deal with the pure C solution. But I first wanted  
to test other possibilities.
I found there are two approaches. PerlObjCBridge and CamelBones.  
Unfortunately I couldn't find any examples covering what I try to do.  
I tested it with CamelBones first. Maybe someone can tell me whether  
this would be possible with PerlObjCBridge, too.

I played a bit and that's what I figured so far. But unfortunately
I wasn't successfull in creating a CBPerlObject. I tried it from a
Foundation Project.

<objc_code>
#import <Foundation/Foundation.h>
#import <CamelBones/CamelBones.h>

int main (int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // create perl interpreter
    CBPerl *perl = [[CBPerl alloc] init];
    //[perl useWarnings];   // activate warnings
    //[perl useLib:modulePath];
    [perl useModule:@"SomePerl"];
    [perl eval:@"$somePerl = new SomePerl"];
    CBPerlObject *perlO = [perl namedObject:@"somePerl"];

    [pool release];

    return 0;

}
</objc_code>

The SomePerl.pm file looks like this:

<perl_code>
package SomePerl;

use strict;
use warnings;

sub new
{
        my $class = shift;
        my %attr = @_;
        my $self = { %attr };
        return bless ($self,$class);

}

1;
__END__
</perl_code>

The -namedObject: returns a nil pointer, so something goes wrong  
there, but I couldn't figure out what.
As you can see I sent the -useLib: message and extended the library  
search path to where the SomePerl.pm module is. So I guess the module  
itself should be found.
Can someone please give me some hints?

Thx,
Manfred
Sherm Pendley - 27 Oct 2005 02:50 GMT
> I played a bit and that's what I figured so far. But unfortunately
> I wasn't successfull in creating a CBPerlObject.

CBPerlObject is a relic from 0.2.x, from when an Objective-C proxy  
was needed as a stand-in. With 1.0.x, Perl classes, when properly  
declared as subclasses of NSObject, are first-class citizens that  
don't need the proxy.

> <objc_code>
> #import <Foundation/Foundation.h>
[quoted text clipped - 6 lines]
>     // create perl interpreter
>     CBPerl *perl = [[CBPerl alloc] init];

CBPerl is a singleton, so it's better to use the class method to  
access the shared instance:

        CBPerl *perl = [CBPerl sharedPerl];

>     //[perl useWarnings];   // activate warnings
>     //[perl useLib:modulePath];
>     [perl useModule:@"SomePerl"];

The following two lines should be replaced:

>     [perl eval:@"$somePerl = new SomePerl"];
>     CBPerlObject *perlO = [perl namedObject:@"somePerl"];

Should be:

        id perlO = [[NSClassFromString(@"SomePerl") alloc] init];

Note that perlO is typed as "id". That's necessary because the  
compiler doesn't know about the SomePerl class at compile time. The  
call to NSClassFromString() is needed for the same reason.

>     [pool release];
>
>     return 0;
>
> }
> </objc_code>

...snip...

SomePerl.pm should look like this:

    package SomePerl;

    use CamelBones qw(:All);

    use strict;
    use warnings;

    class SomePerl {
        'super' => 'NSObject',
        'properties' => [ 'foo', 'bar', 'baz' ],
    };

    sub init : Selector(init) ReturnType(@) {
        my ($self) = @_;
        $self = $self->SUPER::init();

        # Do other initialization

        return $self;
    }

Note that object creation follows Cocoa, rather than Perl  
conventions. You use the inherited alloc() class method to create an  
instance, and initialize the instance by overriding the init()  
instance method, making sure to call the superclass' init() first.

The call to class() and the method attributes are key here. The class
() function registers the Perl class and its methods with the  
Objective-C runtime. The attributes are used to declare the selector,  
argument, and return types with which the method can be called from  
Objective-C. So, for instance, let's say you have a method that, in  
Objective-C, would be declared like this:

    - (id) doFoo:(id)foo withBar:(id)bar options:(int)opts;

In Perl, you'd write it like this:

    sub doFoo_withBar_options : Selector(doFoo:withBar:options:)  
ReturnType(@) ArgTypes(@@i) {
        my ($self, $foo, $bar, $opts) = @_;
    }

The 'properties' hash key defines a list of, ummm, properties. ;-)  
KVC-compliant accessor methods are defined for each, so they can be  
used as outlets, in Cocoa Bindings, etc. For instance, declaring the  
property 'foo' would cause the following accessor methods to be  
defined, that can be called from both Objective-C and Perl:

    sub foo : Selector(foo) ReturnType(@) {
        my ($self) = @_;
        return $self->{'foo'};
    }

    sub setFoo : Selector(setFoo:) ArgTypes(@) {
        my ($self, $value) = @_;
        $self->{'foo'} = $value;
    }

sherm--

Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
Manfred Bergmann - 27 Oct 2005 03:27 GMT
Thanks sherm for replying.

Am 27.10.2005 um 11:50 schrieb Sherm Pendley:

> CBPerl is a singleton, so it's better to use the class method to  
> access the shared instance:
>
>         CBPerl *perl = [CBPerl sharedPerl];

That doesn't work here. Get a nil pointer returned.

> Should be:
>
[quoted text clipped - 3 lines]
> compiler doesn't know about the SomePerl class at compile time. The  
> call to NSClassFromString() is needed for the same reason.

That either returns a nil pointer. Where does the ObjC runtime system  
look for the SomePerl.pm file.
I placed it in some locations, so it should be found by whom ever. ;)
How does this work in general, maybe I can figure out where the  
problem is.

> SomePerl.pm should look like this:
>
[quoted text clipped - 18 lines]
>         return $self;
>     }

Ok, done that.

Regards,
Manfred
Sherm Pendley - 27 Oct 2005 04:02 GMT
> Am 27.10.2005 um 11:50 schrieb Sherm Pendley:
>
[quoted text clipped - 4 lines]
>
> That doesn't work here. Get a nil pointer returned.

I forgot a recent addition, sorry. Should be:

        #import <CamelBones/AppMain.h>
        [CBPerl stubInit: CBGetPerlArchver()];
        CBPerl *perl = [CBPerl sharedPerl];

>>         id perlO = [[NSClassFromString(@"SomePerl") alloc] init];
>>
[quoted text clipped - 4 lines]
> That either returns a nil pointer. Where does the ObjC runtime  
> system look for the SomePerl.pm file.

As far as the ObjC runtime goes, if a class hasn't yet been  
registered, it calls a CamelBones "class handler" function. That  
function tries to do an ordinary "use ClassName" to try to load and  
register the class. That "use" looks in the standard @INC.

When CamelBones starts up, it adds the Resources/ sub-directories of  
all linked frameworks and bundles (including the .app bundle) to  
@INC, and platform- and version- specific subdirectories under that.  
For instance, on Tiger it would add:

    Resources/
    Resources/5.8.6/
    Resources/5.8.6/darwin-thread-multi-2level/

This is repeated whenever a new bundle is loaded by way of NSBundle  
methods - any Objective-C classes in the bundle are automatically  
wrapped to be visible from Perl, and the bundle's Resources/ sub-
directory is added to @INC.

sherm--

Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
Manfred Bergmann - 27 Oct 2005 04:27 GMT
Ok, that worked. Thanks.

Hmm, how come that I couldn't find any documentation about this? All  
I found was a little example code on a japaneese internet site where  
you couldn't read anything except the code snippet itself. :) This  
was, as you said, an old example with CBPerlObject but it gave me a  
hint how to begin at all with that.
Or maybe I am just incapable of searching in the internet. ;)
I figured CamelBones is pretty nice, not only for doing complete Perl-
Cocoa applications for which a lot of examples exist.

Ok, another question.
I guess the Xcode codesence is not working for any Perl classes and  
methods, right?
And can I somehow get rid of the warning message from gcc that the  
object xxx might not respond to method yyy if calling a method of a  
Perl class?

Manfred

Am 27.10.2005 um 13:02 schrieb Sherm Pendley:

>> Am 27.10.2005 um 11:50 schrieb Sherm Pendley:
>>
[quoted text clipped - 43 lines]
> Cocoa programming in Perl: http://camelbones.sourceforge.net
> Hire me! My resume: http://www.dot-app.org
Joel Rees - 27 Oct 2005 04:34 GMT
> Ok, that worked. Thanks.
>
[quoted text clipped - 6 lines]
> I figured CamelBones is pretty nice, not only for doing complete
> Perl-Cocoa applications for which a lot of examples exist.

Too many of us who would like to use it don't have enough time to,
which is a shame.

> [...]
Sherm Pendley - 27 Oct 2005 05:16 GMT
> Hmm, how come that I couldn't find any documentation about this?

Because I haven't written any. ;-)

Why haven't I written any? Because I haven't really considered this  
side of things - calling Perl from Objective-C - as being "final". It  
has been primarily an internal API, and as you've seen from the old  
code you looked at, things have changed substantially. It's pretty  
well settled down at this point though, so it might well be time to  
write those docs.

> I guess the Xcode codesence is not working for any Perl classes and  
> methods, right?

No, it's not. It doesn't know about the Perl debugger either.

> And can I somehow get rid of the warning message from gcc that the  
> object xxx might not respond to method yyy if calling a method of a  
> Perl class?

You could do what Apple does with delegate methods - declare them in  
a category of NSObject:

@interface NSObject (MyPerlClassMethods)
    - (id) doFoo:(id)foo;
@end

You don't have to provide an @implementation for them - that's in  
Perl. If you declare them in the main @interface, but don't provide  
an @implementation, the linker complains. But, with the declarations  
in a category, the linker is quiet. That's by design, for situations  
like this, where you need to declare an interface for methods that  
are not loaded until run time.

sherm--

Cocoa programming in Perl: http://camelbones.sourceforge.net
Hire me! My resume: http://www.dot-app.org
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.