Calling Python from ECLiPSe — PyCLP productive documentation

# Calling Python from ECLiPSe

It is possible to call python function from ECLiPSe.

## How to define a python function call it from ECLiPSe

The steps to achieve this are quite simple.

- Define a python function.

- Register it using function `pyclp.addPythonFunction()`

- Call from ECLiPSe with `call_python_function` predicate.

### Python function definition

Python function tha implement the predicate shall have one argument. This argument will be used to pass a list of the term used in the invocation. Python function shall return the following values `pyclp.SUCCEED` or `pyclp.FAIL` any other values are equivalent to `pyclp.FAIL` It can be called in this function a `pyclp.unify()` to unify to term and interact with ECLiPSe term.

Example:

    def py_unify(args):
       return pyclp.unify(args[0],args[1])

### Register python function for calling

In order to be able to excute a python function from ECLiPSe it is required to register the function by calling `pyclp.addPythonFunction()` after having executed `pyclp.init()`

Example:

    init()
    pyclp.addPythonFunction("my_unify",py_unify)

### Call python function from ECLiPSe

To excecute the python function from ECLiPSe use `call_python_function` predicate. This predicate is declared in `pyclp` module. This shall be imported in the user module. `pyclp` is created when `pyclp.init()` is executed and it is automatically imported in the `eclipse` module (the default one)

Example:

> `use_module pyclp` `call_python_function("my_unify",[A,B])`

## Modify ECLiPSe variables

In the python function it is possible to use all class to represent ECLiPSe object like: `pyclp.Atom()`, `Compound()` etc.. but not `pyclp.resume()`,:py:meth:pyclp.init, `pyclp.cut()` and `pyclp.cleanup()`

## Handling python exceptions

Exception raised in the python function it is stored and reraised inside the `pyclp.resume()` function if a ECLiPSe signal `python_error` is not masked by ECLiPSe.

Internal sequence of operations:

    python script          ECLiPSe                  user python function

    resume()       ---->
                           call_python_function --->
                                                     raise exception
                                                     (exception stored)
                                                     signal event "python_error"
                                                <--
                           if not masked
                           send THROW to resume
                   <----
     if the event
     is "python_error"
     restore exception
     and raise it.

## Complete Example

Example:

    from pyclp import *

    def external_predicate(arguments):
       #arguments store all arguments passed with call_python_function
       #Note unify usage
       return unify(arguments[0],arguments[1])

    init()   #Init ECLiPSe engine
    #Register function with 'my_name' atom
    add_python_function('my_name',external_predicate)
    my_var=Var()
    # call_python_function,'my_name',[1,My_var])
    Compound('call_python_function',Atom('my_name'),[1,my_var]).post_goal()
    resume()
    if my_var.value() != 1:
       print("Failed resume ")

If an exception is raised during the python function execution `abort` event will be raised by ECLiPSe with the following message. If this event will be handled by the user in ECLiPSe program, ECLiPSe engine will send a message to python (FLUSHIO) and then THROW value. See the below example.