<div dir="ltr"><div><div>In the email below, I address the follow-up questions you passed to the answers I passed in the previous email, mention reasons for why we recognize those rules I described, and I also pass another three practices regarding FFI development, and two questions that neither the manual nor the mailing list afaik have addressed, that are vital to how FFI:s are best designed.<br>
<br><br><br><div class="gmail_quote">2008/9/5 Joel J. Adamson <<a href="mailto:adamsonj@email.unc.edu">adamsonj@email.unc.edu</a>> <span dir="ltr"><<a href="mailto:adamsonj@email.unc.edu">adamsonj@email.unc.edu</a>></span><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Thanks so much for the tips; I have some follow-up questions:<br>
<br>
>>>>> "MM" == Mikael More <<a href="mailto:mikael.more@gmail.com">mikael.more@gmail.com</a>> writes:<br>
<br>
    MM>  - Throwing exceptions with no handler/catcher may sigsegv your<br>
    MM> app.<br>
<br>
Good to know, I was unaware of this.</blockquote><div><br>We saw this in threads, i.e. we got sigsegv when the thunk of a threads throws an exception and there was no exception handler.<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
<br>
    MM>  - You should presuppose that ___argXX variables inside<br>
    MM> Scheme-to-C calls are trashed after C-to-Scheme calls. I.e.: If<br>
    MM> you have declared a c-define or c-lambda that takes parameters,<br>
    MM> these will appear as ___arg0, ___arg1 etc. in the C code of the<br>
    MM> c-define / c-lambda. These will have correct contents all until<br>
    MM> you invoke Scheme functions from the C code. not afterwards.<br>
<br>
Okay, take the following functions, that may be the source of the<br>
problem:<br>
<br>
/*  C function for transferring vectors */<br>
int f64vector_length (___SCMOBJ);<br>
double f64vector_ref (___SCMOBJ, int);<br>
double * scm_vector_to_C (___SCMOBJ f64vec)<br>
{<br>
  /* initialize the length of the vector */<br>
  int len = f64vector_length (f64vec);<br>
  /* initializes the new vector */<br>
  double * newCvec = malloc (len*sizeof (double));<br>
  /* declare a counter */<br>
  int i;<br>
  /* iterate over the length of the vector copying each object into<br>
     the new vector */<br>
  for (i = 0; i<len; i++)<br>
    {<br>
      /* could be re-written using pointer arithmetic */<br>
      newCvec[i] = f64vector_ref (f64vec, i);<br>
    }<br>
  return newCvec;<br>
}</blockquote><div><br>Can you please provide the complete c-lambda for this one?<br> <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
<br>
and then the corresponding "c-define"s:<br>
<br>
;; Scheme function for getting data out of f64vectors<br>
(c-define (proc1 f64vec i)<br>
          (scheme-object int)<br>
          double<br>
          "f64vector_ref" ""<br>
          (f64vector-ref f64vec i))<br>
<br>
(c-define (proc2 f64vec)<br>
          (scheme-object)<br>
          int<br>
          "f64vector_length" ""<br>
          (f64vector-length f64vec))<br>
<br>
    MM> So back them up to the stack if you do.<br>
<br>
Forgive my ignorance of C, but how do I do that?  (where the heck is<br>
this stack that everyone speaks of?)</blockquote><div><br>In C, "the stack" == "local variables". Back up to stack == make local variables and store there.<br> <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
<br>
Now, I also noticed this passage in the C-interface chapter of the<br>
manual:<br>
<br>
,----<br>
|  Within the C code the variables `___arg1', `___arg2', etc. can be<br>
| referenced to access the converted arguments.  Similarly, the result to<br>
| be returned from the call should be assigned to the variable `___result'<br>
| except when the result is of type `struct', `union', `type', `pointer',<br>
| `nonnull-pointer', `function' or `nonnull-function' in which case a<br>
| pointer must be assigned to the variable `___result_voidstar' which is<br>
| of type `void*'.  For results of type `pointer', `nonnull-pointer',<br>
| `function' and `nonnull-function', the value assigned to the variable<br>
| `___result_voidstar' must be the pointer or function cast to `void*'.<br>
`----<br>
<br>
However, I have functions like this:<br>
<br>
(define make-gsl-matrix<br>
  (c-lambda (int int scheme-object)<br>
            gsl-matrix*<br>
            "gsl_matrix * ___matrix = gsl_matrix_alloc (___arg1, ___arg2);<br>
            ___matrix->data = scm_vector_to_C (___arg3);<br>
            ___matrix->size1 = ___arg1;<br>
            ___matrix->size2 = ___arg2;<br>
            ___result_voidstar = ___matrix;"))</blockquote><div><br>The rule about backing up arguments to the stack to save argument value contents from being lost before calling Scheme functions from C, when in a call to C from Scheme, would in the case of the c-lambda above translate into:<br>
<br><div style="margin-left: 40px;">(define make-gsl-matrix<br>
  (c-lambda (int int scheme-object)<br>
            gsl-matrix*<br>
            "int a1 = ___arg1; int a2 = ___arg2; int a3 = ___arg3;<br>
            gsl_matrix * ___matrix = gsl_matrix_alloc (___arg1, ___arg2);<br>
            ___matrix->data = scm_vector_to_C (a3);<br>
            ___matrix->size1 = a1;<br>
            ___matrix->size2 = a2;<br>
            ___result_voidstar = ___matrix;"))<br></div> <br>( I do not know if the rule applies to c-lambdas with particular argument counts. The case we tracked down was a c-lambda taking over ten arguments. Also I have no idea if the rule applies to very basic procedures such as car, cdr, +, etc. )<br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>
<br>
It seems that this is seriously wrong, according to the paragraph above:<br>
the last line should be<br>
<br>
___result_voidstar = (void*)___matrix;<br>
<br>
and the return type should be void* and not gsl-matrix*, defined as<br>
follows:<br>
<br>
(c-define-type gsl-matrix*<br>
               (pointer "gsl_matrix"<br>
                        gsl-matrix*))<br>
<br>
But then the question becomes how do I access the result I need?  I<br>
would much rather have a function that returns a matrix as a result<br>
(functional style) rather than having it imperatively modify an existing<br>
variable, a la C.</blockquote><div><br>Returning a gsl-matrix* from a c-lambda is perfectly fine.<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
<br>
Thanks for your help!<br>
<div><div></div><div class="Wj3C7c">Joel<br>
<br>
</div></div></blockquote><div><br> ## You may want to hook a release function to it also, that is a function
that will perform the garbage collection for variables of this type,
when the garbage collector invokes it to.<br>
<br>
Example:<br>
<br>
<div style="margin-left: 40px;">(c-declare #<<c-declare-end<br>
<br>
___SCMOBJ release_cell_star(void* p) {<br>
     if (p == 0)<br>
          fprintf(stderr,"release_cell_star: Called with null parameter! Internal inconsistency !! Ignoring.\n");<br>
     else {<br>
          delete (Cell*) p;<br>
     }<br>
<br>
     return ___FIX(___NO_ERR);<br>
}<br>
<br>
c-declare-end<br>)<br>
<br>
(c-define-type Cell* (pointer "Cell" Cell* "release_cell_star"))<br>
</div>
<br>The example above is for freeing a C++ object. In C, you would typically have  free(p); instead of delete (Cell*) p; .<br><br><br>
<br> ## Be careful never to reintroduce a pointer to a structure from the C world into the Scheme world twice, so that the garbage collector would trig twice. Examples: <br><br>OK:<br><br><div style="margin-left: 40px;">
(c-declare #<<c-declare-end<br>
<br>
___SCMOBJ release_mystruct_star(void* p) {<br>
     if (p == 0)<br>
          fprintf(stderr,"release_mystruct_star: Called with null parameter! Internal inconsistency !! Ignoring.\n");<br>
     else {<br>
          delete (Cell*) p;<br>
     }<br>
<br>
     return ___FIX(___NO_ERR);<br>
}<br>
<br>
c-declare-end<br>)<br><br>(c-define-type MyStruct* (pointer "MyStruct" MyStruct* "release_mystruct_star"))<br>
<br><br></div>OK:<br></div><div><div style="margin-left: 40px;"><br>(define create-mystruct (c-lambda () MyStruct* #<<c-lambda-end<br><br>___result_voidstar = (void*) [ some code that allocates a new MyStruct ];<br>
<br>c-lambda-end<br>))<br><br></div></div></div><br><u>NOT</u> OK. The reason it's not OK is because the MyStruct* is reintroduced from the C world to the Scheme world when create-mystruct returns.<br>

<div style="margin-left: 40px;"><br>(define create-mystruct (c-lambda () MyStruct* #<<c-lambda-end<br><br>___result_voidstar = (void*) construct_my_returnvalue([ some code that allocates a new MyStruct ]);<br><br>c-lambda-end<br>
))</div><br><div style="margin-left: 40px;">(c-define (construct-my-returnvalue struct)<br>          (MyStruct*)<br>          MyStruct*<br>          "construct_my_returnvalue" "static"<br>          [ code ] )<br>
</div><br><br>OK:<br><br><div style="margin-left: 40px;">(define create-mystruct (c-lambda () scheme-object #<<c-lambda-end<br><br>___result = construct_my_returnvalue([ some code that allocates a new MyStruct ]);<br>
<br>c-lambda-end<br>))<br><br></div>
<div style="margin-left: 40px;">(c-define (construct-my-returnvalue struct)<br>
          (MyStruct*)<br>
          scheme-object<br>
          "construct_my_returnvalue" "static"<br>
          [ code ] )<br>
</div>
<br><br>Function that reintroduces a MyStruct* from the C world to the Scheme world. <u>NOT</u> OK:<br><br><div style="margin-left: 40px;">(define do-something-with-mystruct (c-lambda (MyStruct*) MyStruct* #<<c-lambda-end<br>
<br>[code that does something with ___arg1]<br><br>
___result_voidstar = ___arg1;<br><br>
c-lambda-end<br>))<br><br></div>


<br>Function that reintroduces a MyStruct* from the C world to the Scheme world. OK:<br><br><div style="margin-left: 40px;">(define (do-something-with-mystruct MyStruct*)<br>  (do-something-with-mystruct MyStruct* MyStruct*))<br>
<br>(define do-something-with-mystruct-private (c-lambda (MyStruct* scheme-object) scheme-object #<<c-lambda-end<br><br>
[code that typecasts ___arg1 to a MyStruct and does something with ___arg1]<br><br>

___result = ___arg2;<br><br>

c-lambda-end<br>))<br></div>






<br><br>Function that reintroduces a MyStruct* from the C world to the Scheme world. <u>NOT</u> OK,   What makes it not OK is two things: first, it reintroduces MyStruct* from the C world to the Scheme world when invoking construct_my_returnvalue, then it reintroduces it yet another time when do-something-with-mystruct returns.<br>
<br><div style="margin-left: 40px;">(define do-something-with-mystruct (c-lambda (MyStruct*) MyStruct* #<<c-lambda-end<br><br>[code that does something with ___arg1]<br><br>
___result_voidstar = construct_my_returnvalue(___arg1);<br><br>
c-lambda-end<br>))<br><br>(c-define (construct-my-returnvalue struct)<br>          (MyStruct*)<br>          MyStruct*<br>          "construct_my_returnvalue" "static"<br>          [ code ] )<br></div>

<br><br>


<br>Function that reintroduces a MyStruct* from the C world to the Scheme world. OK:<br><br></div><div style="margin-left: 40px;">(define (do-something-with-mystruct MyStruct*)<br>  (do-something-with-mystruct MyStruct* MyStruct*))<br>
<br>(define do-something-with-mystruct-private (c-lambda (MyStruct* scheme-object) scheme-object #<<c-lambda-end<br><br>
[code that typecasts ___arg1 to a MyStruct and does something with ___arg1]<br><br>

___result = construct_my_returnvalue(___arg2);<br><br></div><div style="margin-left: 40px;">

c-lambda-end<br></div><div style="margin-left: 40px;">))<br></div><div style="margin-left: 40px;"><div style="margin-left: 40px;"><br></div></div><div style="margin-left: 40px;">
(c-define (construct-my-returnvalue struct)<br>
          (scheme-object)<br>
          scheme-object<br>
          "construct_my_returnvalue" "static"<br>
          [ code ] )<br></div>






<br></div><div><br><br> ## Note that there is no handling mechanism, such as garbage collection, to free C frames.<br><br>Background:<br><br>In Scheme code, the garbage collector always has perfect handling of your variables in all situations: you may have whatever complex patterns of execution, throw exceptions anywhere, and invoke thread-terminate! on any thread, and the garbage collector will always ensure that allocated memory that will never more be relevant will be garbage collected.<br>
<br>This does not apply to c-lambdas: C code has a static stack structure. If C function A invokes C function B that invokes C function C, these are always returned in the same order, i.e. C returns to B that returns to A. (The same applies to C++.) Since there are no continuations or closures, there is <u>NO</u> way for B to, for instance,<br>
<br> - call some code from within A during its execution<br> - save its state to variable D, return into A, and then continue at D.<br><br>The only thing B can do about A's future execution and state, is to<br><br> - modify variables A has access to, if B has references to them<br>
 - return to A, possibly returning a return value<br> - in the case of C++, throw an exception.<br><br>Consequences:<br><br>When combining C and Scheme code, you must ensure that you call c-lambda:s in a way that is in alignment with the way C works.<br>
<br>The rules here are:<br><br> * If you call Scheme code from within C code, always ensure that you return back from the Scheme code to the C code.<br><br></div><div><div style="margin-left: 40px;">I.e., ensure the thread will not be terminated, and that the Scheme code called from the C code will not throw exceptions that will not be continued.<br>
<br>Applied to the examples above, do <u>not</u> do (thread-terminate! (current-thread)) or (raise) from within construct-my-returnvalue.<br><br>As regards thread termination:<br><br><div style="margin-left: 40px;">As Gambit is a multitasking environment, you must also ensure that no other part of your application hinders the return of a C-to-Scheme call.<br>
<br></div></div></div><div><div style="margin-left: 120px;"> * A way to ensure this partially **could** be to compile the Scheme functions you call from Scheme code with (declare (not interrupts-enabled)), but beware, perhaps your Scheme code invokes other Scheme code that has (declare (interrupts-enabled)). (Whether routines such as + and car are relevant to this, I have no idea.)<br>
<br> * If your application uses multiple threads, and there are instances when these perform thread-terminate!, another way to ensure this partially could be to have a separate thread for execution of c-lambda:s. For example:<br>
<br><div style="margin-left: 40px;">(define (worker-thread-thunk)<br>  ((thread-receive))<br>  (worker-thread-thunk))<br><br>(define worker-thread  ; CPU cheap. Start on load is ok.<br>  (thread-start! (make-thread worker-thread-thunk)))<br>
<br>(define (perform-in-worker-thread thunk)<br>  (let ((mailbox (make-empty-mailbox)))<br>    (thread-send worker-thread<br>                 (lambda ()<br>                   (mailbox-put! mailbox<br>                                 (with-exception-catcher<br>
                                  (lambda (e) (lambda () (raise e)))<br>                                  thunk))))<br>    (mailbox-get! mailbox)))<br><br></div></div><div style="margin-left: 120px;">The mailbox code is found in the Gambit manual.<br>
</div><div style="margin-left: 40px;"><br>As regards exceptions:<br><br><div style="margin-left: 40px;">Never throw an exception from Scheme code that is invoked by C code, that you will not be continued.<br><br>If you would happen to have a Scheme function generate a return value for a c-lambda (  Usually, I suppose, that this should be completely unnecessary, and should not be adviced, though I have not seen examples of how to construct return value structures such as lists in C. Could someone who knows perhaps provide us with some examples that do this, and are thread-safe as well, Marc ?   ), one way to get around the risk of it throwing exceptions would be to stuff the return value generating code in a closure, i.e., rather than:<br>
<br></div></div><div style="margin-left: 40px;"><div style="margin-left: 40px;"><div style="margin-left: 40px;">(define a (c-lambda () scheme-object #<<c-lambda-end<br><br>..code..<br><br>MyStruct* mystruct = ..code..;<br>
<br>___result_voidstar = construct_my_returnvalue(mystruct etc. );<br><br>
c-lambda-end<br>))<br><br>(c-define (construct-my-returnvalue struct etc.)<br>          (MyStruct* etc.)<br>          scheme-object<br>          "construct_my_returnvalue" "static"<br>
          (if conditions<br>
            (error " AN ERROR ")<br>
            struct))<br></div><br>Do:<br><br></div></div><div style="margin-left: 40px;"><div style="margin-left: 40px;"><div style="margin-left: 40px;">(define (a)<br>  ((a-private)))<br><br>(define a-private (c-lambda () scheme-object #<<c-lambda-end<br>
<br>
..code..<br><br>
MyStruct* mystruct = ..code..;<br><br>
___result_voidstar = construct_my_returnvalue(mystruct etc. );<br><br>

c-lambda-end<br>
))<br><br>
(c-define (construct-my-returnvalue struct etc.)<br>
          (MyStruct* etc.)<br>
          scheme-object<br>
          "construct_my_returnvalue" "static"<br>
          (lambda ()<br>
            (if conditions<br>

              (error " AN ERROR ")<br>

              struct)))</div></div></div><br></div><div><br> * Do not return multiple times into C code <br><br><div style="margin-left: 40px;">That is, C code is not compliant with continuations.<br><br>(I have no idea what happens if you would do this.)<br>
</div><br><br>Then, there is one more relevant design aspect to Gambit here, that neither the manual nor the mailing list afaik has addressed:<br><br>Must c-lambda:s be returned in the exact inverse order as they were invoked, or can they be returned in other orders also?<br>
<br>Whether this is so or not has great impact on how code that combines use of threads and/or closures and/or continuations with c-code that calls Scheme.<br><br>An example where it would have impact: Start two threads that invoke the example procedure a above an unlimited number of times, i.e.,<br>
<br><div style="margin-left: 40px;">(define (spawn-a) (thread-start! (make-thread (lambda () (let loop () (a) (loop))))))<br>(define first-thread (spawn-a))<br>(define second-thread (spawn-a))<br></div>

<br> At some point, this will happen:<br><br> 1. a is invoked in the first thread. construct_my_returnvalue is entered in the first thread.<br> 2. The scheduler switches current thread of execution from the first thread to the second thread.<br>
 3. a is invoked in the second thread. construct_my_returnvalue is entered in the second thread.<br> 4. The scheduler switches current thread of execution from the second thread to the first thread.<br> 5. construct_my_returnvalue returns in the first thread. a returns in the first thread.<br>
<br>Is Gambit designed in a way that allows this? If not, what do you consider the best strategies to safeguard against this ever happening?<br>If it is, how are C frames rewinded? In the example above, right after a returns at 5., will its C frame be freed, or will this happen first when the C frame allocated in 3. is freed also?<br>
<br>Marc or anyone who knows, how does Gambit work in this respect?<br><br>Mikael<br><br><br></div></div>