Interoperability

Amber code can interoperate in many different ways with code written in other languages.

Quick links

Wrap a Parrot class

To wrap a Parrot class so that it can be used seamlessly from Amber, use an external parrot declaration.

If the external class is a built-in Parrot PMC class, you may optionally indicate this by using an external pmc declaration, which may enable Amber to generate more efficient code.

For example, the Amber kernel class INTEGER wraps the built-in Parrot PMC class Integer:

class INTEGER external pmc @@Integer ... end

Wrap and extend a Parrot class

A Parrot class that has been wrapped can be extended by adding one or more routines.

For example, the Amber kernel class INTEGER wraps and extends the built-in Parrot PMC class Integer:

class INTEGER external parrot @@Integer public -- queries abs -- Absolute value ... public -- iterators times(proc) -- proc: AGENT -- Execute 'proc' the same number of times as the value of 'current', -- or zero times if 'current' is negative. -- Example usage: 5.times(do print_line("Hello") end) ... end

Inherit from a Parrot class

To inherit from a Parrot class, first wrap it with an Amber class.

For example, the Amber kernel class CHARACTER inherits from the Amber class INTEGER which wraps the built-in Parrot PMC class Integer:

class CHARACTER inherit INTEGER ... end

Write an Amber routine in PIR

You can write an Amber routine in PIR (Parrot Intermediate Representation), perhaps to gain access to low-level Parrot facilities. You can even add Amber preconditions and postconditions to a PIR routine.

Use the external keyword in the feature definition, as in this example from class INTEGER:

abs -- Absolute value external pir ".check_args(0, 'Integer.abs')" "result = new Undef" "result = abs self" end

If your routine has formal arguments, Amber inserts the appropriate '.param' declarations before your PIR code. Amber also encloses your PIR code between the following lines:

.local pmc result ... .return(result)

Call a built-in Parrot routine

You can call a built-in Parrot routine with an Amber object as the call target, by preceding it with '@'.

The following Amber instructions both print "9". The first instruction calls the Amber infix "+" operator. The second instruction calls the built-in Parrot addition routine "__add":

print_line(5 + 4) print_line(5.@__add(4))

Assign a Parrot object to an Amber entity

You can assign any Parrot object to an Amber entity, regardless of the language in which the Parrot object is implemented.

To create a Parrot object, precede the classname with '@@'. Then, assign it to an Amber object using the standard Assignment_instruction.

The following example creates an instance of the standard Parrot class Random and assigns it to a local variable 'r':

local r do r := @@Random ... end

You can optionally indicate a built-in Parrot PMC type by adding a dot before the classname, which may enable Amber to generate more efficient code.

At the time of writing (July 2005) it is not possible to pass arguments to the constructor of the Parrot object, but this restriction may be lifted in a future release of Amber.

Create an Amber object and assign it to a PIR variable

You can assign any Amber object to a PIR (Parrot Intermediate Representation) variable.

Enclose the Amber classname in single-quotes or double-quotes, then use the PIR 'new' instruction with a local PIR variable of type pmc:

.local pmc x x = new 'MY_CLASS'

Call an Amber routine from PIR

From PIR, you can call an Amber routine on an Amber object. You can also call an Amber routine on a Parrot object that has been extended using Amber.

Suround the Amber routine name by single-quotes or double-quotes. You can pass arguments to the routine (surrounded by parentheses). You need to include the parentheses even if there are no arguments:

.local pmc x .local pmc result x = new 'MY_CLASS' # 'MY_CLASS' is a user-written Amber class result = x.'my_routine'()

Call a dynamic link library (.dll or .so)

By using Amber routines with bodies written in PIR you can use the facilities that Parrot provides to call routines in dynamic link libraries (*.dll or *.so). It doesn't matter what language the DLL was originally written in, provided that its data types map to the datatypes supported by Parrot for its Native Call Interface functions.

This example calls get_current_dir_name from libc (the standard GNU C library):

initialize_libc_wrapper if is_defined(libc_wrapper) then print_line("Current directory is: " & current_working_directory) else print_line("Could not load libc.") end private initialize_libc_wrapper external pir ".local pmc libc" "loadlib libc, '/lib/libc.so.6'" "setattribute self, 'libc_wrapper', libc" end current_working_directory external pir ".local pmc libc" ".local pmc get_current_dir" ".local string dir" "libc = getattribute self, 'libc_wrapper'" "dlfunc get_current_dir, libc, 'get_current_dir_name', 'tv'" "dir = get_current_dir()" "result = new .String" "result = dir" end libc_wrapper end

If you need to pass structures to and from DLL routines, you can use the ManagedStruct and UnManagedStruct PMC classes included with Parrot.

sh: /home/web/cgi/eiffelzone/comments.exe: No such file or directory