[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: embedding mzscheme into a C++ application



Quoting Chris Uzdavinis:
> > One possibility is to diallow the jump.
> 
> What consequences follow when this route is taken?  (Other than not
> being able to jump?)

Probably the only notable consequence is that exception handling will
not work the way the Scheme programmer expects: the exception is
silently "handled" at the point where the jump is blocked.

> > If so, couldn't you catch the longjmp at the C++->Scheme boundary,
> > raise a C++ exception, catch the exception at the Scheme->C++ entry
> > point, and longjmp again?
> 
> I think that would work.  But there is an uncertainty of what the
> stack variables values are when the longjmp is "caught".  Do they
> revert to the value they had at the time setjmp was called, or do they
> retain their value from when they called into the next function (which
> eventually lead up to the longjmp)?  We need to make sure that the
> values are not rolled back, so additionally, we must declare all the
> stack-based objects as being "volatile."

I'm not sure what you mean. I imagine that the `setjmp' appears just
before the call into Scheme, and you'll only need `volatile' on local
variables in that function using `setjmp'. The other stack variables
will be fine.

> One final question on this issue then: if I want to implement your
> suggestion, by re-longjmp-ing at the end of my C++ function, how do I
> know which jump-buffer to longjmp into?  (I'm not terribly familiar
> with longjmp, as it's fairly strongly discouraged in C++.)  Is there a
> way to ask for the "next higher" jump buffer... which is where the
> jump would have gone had I not intercepted it?

Before using `setjmp' on `scheme_error_buf' to catch jumps, save the
content of `scheme_error_buf'. Copy the content back after catching a
jump or after a normal return. Something like this:

  mz_jmp_buf save;
  memcpy(&save, &scheme_error_buf, sizeof(mz_jmp_buf));
  if (scheme_setjmp(scheme_error_buf)) {
    /* jump */
    memcpy(&scheme_error_buf, &save, sizeof(mz_jmp_buf));
    ... raise a C++ exception ...
  } else {
    scheme_eval_string("x", scheme_env); /* or some other scheme_ call */
  }
  memcpy(&scheme_error_buf, &save, sizeof(mz_jmp_buf));
  /* Normal return... */

Then, when you catch the C++ exception at the the Scheme->C++ boundary,
use `scheme_longjmp(scheme_error_buf, 1)'.

Matthew