๐Ÿš€ go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: gmane.comp.ai.prolog.swi
1 messages
1 total messages Started by Lionel Ains Tue, 16 Apr 2002 19:44
Re[1] foreign interface: Raising Prolog exception in nested C functions
#27
Author: Lionel Ains
Date: Tue, 16 Apr 2002 19:44
180 lines
5690 bytes
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

--=_NextPart_Caramail_0176531018975493_ID
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Hi Jan,

Thanks for the information you provided.
To answer your question, my exception would be raised in C
within compute_sth_from(). Let's say that my C code in
compute_sth_from() is:

---
foreign_t compute_sth_from(int i) {

term_t exception;

 if (i==3) {
 exception=PL_new_term_ref();
 PL_unify_atom_chars(exception,
"exception_from_compute_sth_from");
 return PL_raise_exception(); // This fails, so returns 0
 }
}

foreign_t pl_do_sth() {

int i;

 for (i=0; i<10; i++) {
 if (!compute_sth_from(i)) { // This conditions is treu
if compute_sth_from() failed
 PL_fail; // This will keep the same exception as
created in compute_sth_from()
 }
 }
 PL_succeed;
}
---

This should allow me to propagate exceptions within the C
functions, however, just out of interest, is there a way for
me to handle the difference between having
compute_sth_from(i) failing or raising an exception?
It looks from the manual, in section 6.6.9, that I can only
know whether compute_sth_from() raised an exception or not
by calling it using PL_open_query(), which then means that I
have to register compute_sth_from() as a Prolog predicate,
and modify the arguments to fit with the Prolog-to-C interface.

Can't I make the difference by checking the exception-term
for its content using PL_exception(), and getting the handle
to the current query (using, let's say a C-function "qid_t
PL_get_current_handle")
If so, I could write, in my for loop:

---
 if (!compute_sth_from(i)) { // This conditions is true
if compute_sth_from() failed
 if (PL_exception(PL_get_current_handle)) { // Test if
an exception has already been built by compute_sth_from()
 PL_fail; // This will keep the same exception as
created in compute_sth_from()
 }
 else { // This part of the code will be executed if
compute_sth_from() simply failed (without raising an exception)
 PL_succeed;
 }
 }
---

Is this acceptable, or even feasible (provided an equivalent
to "PL_get_current_handle" would exist in the Prolog foreign
interface)?
Even if all is already exists, isn't there a risk to be
incompatible with further?

I have another concern: is it possible to raise an exception
within the install_t install() and install_t uninstall() C
functions of a C foreign library?

Many thanks for your help,

Lionel

> -------Message d'origine-------
> De : Jan Wielemaker <jan@swi.psy.uva.nl>
> Date : 16/04/2002 15:35:31
>
> On Tuesday 16 April 2002 18:09, Lionel Ains wrote:
> > Let's say that pl_do_sth is the C-implementation associated
> > with the Prolog predicate do_sth/0
> > I would like to allow the C function "compute_sth_from()" to
> > raise exception, that will not be caught by pl_do_sth() and
> > should thus be thrown outside of pl_do_sth(), thus outside
> > of the foreign code, to handle it at the Prolog level.
> > Do I have to declare compute_sth_from() as returning a
> > foreign_t type?
> > How do I test whether compute_sth_from() raised an
> > exception? Do I specifically have to test it, and to
> > manually pass the exception by getting the exception object
> > thrown by compute_sth_from() and re-raise the same in
> > pl_do_sth()?
> >
> > The workaround I am using right now is to make
> > compute_sth_from() return an integer that will be evaluated
> > by pl_do_sth(), which will, in turn, raise an exception
> > according to the value returned. This forces me to repeat
> > the code that raises the exception in all the function that
> > will call compute_sth_from() though... so it's not a very
> > clean way of doing it.
>
> Lionel,
>
> Its not really clear what you want. Is the (possible)
exception
> of compute_sth_from(i) raised in C or from a call-back to
Prolog?
>
> Maybe it helps if I explain how it works. On calling
PL_raise_exception(),
> the term is bound to a global term-reference, called the
`exception-term'.
> If control returns from C to Prolog with failure and there
is a term in
> this exception-term the system will raise a Prolog
exception. Thats
> one part.
>
> If you call Prolog using PL_open_query(), ...,
PL_next_solution(), and
> Prolog raises an exception, this exception is associated
with the query
> and accessible through PL_exception(qid). You can (and
maybe thats the
> trick for you) add PL_Q_PASS_EXCEPTION to the flags of
PL_open_query().
> If you do that, the exception is placed (actually left) in
the same
> `exception-term' and therefore returning with failure from
the foreign
> code will re-raise the exception in the calling Prolog
context.
>
> No one says you need to return immediately after a
PL_raise_exception().
> PL_throw() is an entirely different matter: it long_jmp()s
back into
> the system and should be used with care (as always
required with
> long_jmp()).
>
> There are various examples in the system sources as well
as in the
> C++ interface (if I recall correctly).
>
> 	Cheers --- Jan

______________________________________________________
Personnalise ton rรฉpondeur au 08 99 703 970 (*)
(*) 1,35 Euro/appel + 0,34 Euro/mn


--=_NextPart_Caramail_0176531018975493_ID--


----------------
* To UNSUBSCRIBE, please use the HTML form at

    http://www.swi.psy.uva.nl/projects/SWI-Prolog/index.html#mailinglist

or send mail to prolog-request@swi.psy.uva.nl using the Subject: "unsubscribe"
(without the quotes) and *no* message body.

** An ARCHIVE of this list is maintained at

    http://www.swi.psy.uva.nl/projects/SWI-Prolog/mailinglist/archive/

Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads