Using Perl in Cocoa

2005-10-26 Thread Manfred Bergmann

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




Re: Using Perl in Cocoa

2005-10-26 Thread Sherm Pendley

On Oct 26, 2005, at 8:34 PM, Manfred Bergmann wrote:


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
#import CamelBones/CamelBones.h

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

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



Re: Using Perl in Cocoa

2005-10-26 Thread Manfred Bergmann

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:

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.


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:

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;
}



Ok, done that.


Regards,
Manfred



Re: Using Perl in Cocoa

2005-10-26 Thread Sherm Pendley

On Oct 26, 2005, at 10:27 PM, Manfred Bergmann wrote:


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.


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];

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.


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



Re: Using Perl in Cocoa

2005-10-26 Thread Manfred Bergmann

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:


On Oct 26, 2005, at 10:27 PM, Manfred Bergmann wrote:



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.



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];

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.




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






Re: Using Perl in Cocoa

2005-10-26 Thread Joel Rees


On 2005.10.27, at 12:27 PM, Manfred Bergmann wrote:


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.


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



[...]




Re: Using Perl in Cocoa

2005-10-26 Thread Sherm Pendley

On Oct 26, 2005, at 11:27 PM, Manfred Bergmann wrote:


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