<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>"My" is the struct I've been showing in my other email, defined inside a C-declare and wrapped by c-define-type. </div><div>From gambit's point of viewI it is a scheme-object like everything else, I suppose.</div><div><br></div><div>Here is the code. For whatever reason "new-My" doesn't trigger the bug in my simple use case, even if it returns an object.</div><div>I was wrong about a detail: that bug is also present in linux. Doesn't crash, but corrupts the contents of the structure (!).</div><div><br></div><div><div>;; START</div><div><br></div><div>(c-declare #<<c-declare-end</div><div>typedef struct My {</div><div>      int r;</div><div>} My;</div><div><br></div><div>static ___SCMOBJ ___release_My( void* ptr ) {</div><div>    ___EXT(___release_rc)( ptr );</div><div>    return ___FIX(___NO_ERR);</div><div>}</div><div><br></div><div>// workaround to c-lambda bug (gambit mailing list 2015-12-14</div><div>My indirect_star_to_My(My *ptr) {</div><div>        return *ptr;</div><div>}</div><div>c-declare-end</div><div>)</div><div><br></div><div><br></div><div>(begin</div><div>  (c-define-type My (struct "My"))</div><div>  (c-define-type My* (pointer My (My*)))</div><div>  (c-define-type My*/nonnull (nonnull-pointer My (My*)))</div><div>  (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))</div><div><br></div><div>(define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));"))</div><div>(define *->My (c-lambda (My*/nonnull) My "indirect_star_to_My"))</div><div>(define My-r (c-lambda (My*/nonnull) int "___result = ___arg1->r;"))</div><div>(define My-r-set! (c-lambda (My*/nonnull int) void "___arg1->r = ___arg2;"))</div><div>(define My->* (c-lambda (My) My*/nonnull "___result_voidstar = &___arg1;"))</div><div><br></div><div>;; this one returns My, as a foreign object (struct), not as a foreign object (pointer)</div><div>;; doesn't segfault, at least in my use case. why?</div><div>(define new-My (c-lambda () My "___result_voidstar = ___EXT(___alloc_rc)(sizeof(struct My));"))</div><div><br></div><div>(define (evil)</div><div>   (let* ((xoxo (new-My))</div><div>          (xoxop (My->* xoxo)))</div><div>      (My-r-set! xoxop #xff)</div><div>      (let loop ((c 1))</div><div>          (begin</div><div>              (if (= 0 (remainder c 1000000))</div><div>                  (begin (display c)</div><div><span class="Apple-tab-span" style="white-space:pre">                       </span>             (display "-")</div><div><span class="Apple-tab-span" style="white-space:pre">                   </span>             (display (My-r xoxop))</div><div><span class="Apple-tab-span" style="white-space:pre">                    </span>             (newline)))</div><div>              (loop (+ 1 c))))))</div><div>(evil)</div><div><br></div><div>;; END</div></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><br><div><div>Il giorno 15/dic/2015, alle ore 19:25, Adam <<a href="mailto:adam.mlmb@gmail.com">adam.mlmb@gmail.com</a>> ha scritto:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr">Paolo, wait, what is your definition of your My type here - "scheme-object"?<div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">2015-12-15 3:46 GMT+08:00 Paolo Carlesi <span dir="ltr"><<a href="mailto:pcarlesi@gmail.com" target="_blank">pcarlesi@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Thank you for the workaround!<br>
<br>
What is the best way to generate a foreign c-type object ?<br>
<br>
This seems to me the best approach (sorry if it's obvious to everybody but me):<br>
<br>
(define make-My (c-lambda () My "___result_voidstar = ___EXT(___alloc_rc)(sizeof(struct My));"))<br>
(define My->* (c-lambda (My) My*/nonnull "___result_voidstar = &___arg1;"))<br>
<br>
has the advantage of not wasting time / space creating a new foreign object and a copy, like *->My below does.<br>
It also doesn't trigger the c-lambda bug, not that I have verified carefully yet.<br>
Members can easily be set up with a syntax like (My-x-set! (My->* xoxo) #xdeadbeef) .<br>
Is this approach correct?<br>
<br>
Thanks Again<br>
<span class="HOEnZb"><font color="#888888"><br>
Paolo<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
Il giorno 14/dic/2015, alle ore 18:02, Marc Feeley <<a href="mailto:feeley@iro.umontreal.ca">feeley@iro.umontreal.ca</a>> ha scritto:<br>
<br>
> There appears to be a bug in the FFI when using a c-lambda with inline code that returns a foreign object.  So for now you will have to define a C function that does the work and use the name of that function in the c-lambda.  In other words:<br>
><br>
> (c-declare #<<c-declare-end<br>
><br>
> My indirect_My_star(My *ptr) { return *ptr; }<br>
><br>
> c-declare-end<br>
> )<br>
><br>
> (define *->My (c-lambda (My*/nonnull) My "indirect_My_star"))<br>
><br>
> Marc<br>
><br>
><br>
>> On Dec 14, 2015, at 4:55 AM, Paolo Carlesi <<a href="mailto:pcarlesi@gmail.com">pcarlesi@gmail.com</a>> wrote:<br>
>><br>
>> Hello,<br>
>><br>
>> I'm experiencing regular segfaults on OSX 10.9.5, with the sample code shown below.<br>
>> Tested with Gambit 4.8.1 + GCC 4.9  and with packaged Gambit 4.7.3 + LLVM.<br>
>> No issue at all on Linux, GCC 4.8, with both Gambit 4.2.8 and Gambit 4.8.2.<br>
>> Of course I may be doing something silly.<br>
>><br>
>> A simple struct, "My" is generated inside a c procedure, then passed multiple times to another c-lambda procedure (*->My).<br>
>> It's a simplified model of the code produced by a FFI SDL2 Library I'm using.<br>
>> The doc says that the foreign object (xoxo in the example) should not be released while the scheme code is still referencing it.<br>
>> I am seeing the refcount going wildly in the negative, one for each call to *->My<br>
>> The only way -- clumsy -- I have found to avoid this is to increment the reference count with ___addref_rc ( not shown here ).<br>
>><br>
>> What's wrong here?<br>
>> Thanks!<br>
>><br>
>><br>
>> LLDB output:<br>
>><br>
>> Process 48149 launched: '/Users/paolo/scheme/spazz/fromlin' (x86_64)<br>
>> Process 48149 stopped<br>
>> * thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)<br>
>>   frame #0: 0x000000010000770c fromlin`___release_rc + 28<br>
>> fromlin`___release_rc + 28:<br>
>> -> 0x10000770c:  movq   %rax, (%rdx)<br>
>>  0x10000770f:  movq   %rdx, 0x8(%rax)<br>
>>  0x100007713:  jmp    0x100010240               ; ___free_mem<br>
>>  0x100007718:  nopl   (%rax,%rax)<br>
>><br>
>> stack trace:<br>
>><br>
>> (lldb) bt<br>
>> * thread #1: tid = 0x40e3c9, 0x000000010000770c fromlin`___release_rc + 28, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)<br>
>> * frame #0: 0x000000010000770c fromlin`___release_rc + 28<br>
>>   frame #1: 0x0000000100002579 fromlin`___release_fn0 + 9<br>
>>   frame #2: 0x0000000100009009 fromlin`___garbage_collect + 3497<br>
>>   frame #3: 0x00000001000091bf fromlin`___alloc_scmobj + 255<br>
>>   frame #4: 0x000000010000d4eb fromlin`___POINTER_to_SCMOBJ + 43<br>
>>   frame #5: 0x000000010000d5e4 fromlin`___STRUCT_to_SCMOBJ + 20<br>
>>   frame #6: 0x0000000100002112 fromlin`___H__20_fromlin + 3378<br>
>>   frame #7: 0x0000000100004aa4 fromlin`___call + 372<br>
>>   frame #8: 0x0000000100004bc6 fromlin`___setup_pstate + 262<br>
>>   frame #9: 0x00000001000063be fromlin`___setup + 3950<br>
>> (lldb)<br>
>><br>
>><br>
>> ;; SAMPLE CODE<br>
>><br>
>> (c-declare #<<c-declare-end<br>
>><br>
>> typedef struct My {<br>
>> int r;<br>
>> } My;<br>
>><br>
>> c-declare-end<br>
>> )<br>
>><br>
>> (begin<br>
>> (c-define-type My (struct "My"))<br>
>> (c-define-type My* (pointer My (My*)))<br>
>> (c-define-type My*/nonnull (nonnull-pointer My (My*)))<br>
>> (c-define-type My*/release-rc (nonnull-pointer My (My*) "___release_My")))<br>
>><br>
>><br>
>> (begin<br>
>>   (c-declare #<<c-declare-end<br>
>> static ___SCMOBJ ___release_My( void* ptr ) {<br>
>>   ___EXT(___release_rc)( ptr );<br>
>>   return ___FIX(___NO_ERR);<br>
>> }<br>
>> c-declare-end<br>
>>   )<br>
>><br>
>>   (define alloc-My (c-lambda () My*/release-rc "___result_voidstar = ___EXT(___alloc_rc)( sizeof( struct My ));"))<br>
>>   (define *->My (c-lambda (My*/nonnull) My "___result_voidstar = (My*)___arg1;"))<br>
>>   (define My-r (c-lambda (My*/nonnull) unsigned-int8 "___result = ___arg1->r;"))<br>
>>   (define My-r-set! (c-lambda (My*/nonnull unsigned-int8) void "___arg1->r = ___arg2;")))<br>
>><br>
>> (define (evil)<br>
>>  (let ((xoxo (alloc-My)))<br>
>>     (My-r-set! xoxo #xff)<br>
>>     (let loop ((c 1))<br>
>>         (begin<br>
>>             (if (= 0 (remainder c 10000))<br>
>>                 (begin (display c) (newline)))<br>
>>             (*->My xoxo)<br>
>>             (loop (+ 1 c))))))<br>
>><br>
>> (evil)<br>
>><br>
>> ;;END CODE<br>
>><br>
>><br>
>><br>
>><br>
>> _______________________________________________<br>
>> Gambit-list mailing list<br>
>> <a href="mailto:Gambit-list@iro.umontreal.ca">Gambit-list@iro.umontreal.ca</a><br>
>> <a href="https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list" rel="noreferrer" target="_blank">https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list</a><br>
><br>
<br>
_______________________________________________<br>
Gambit-list mailing list<br>
<a href="mailto:Gambit-list@iro.umontreal.ca">Gambit-list@iro.umontreal.ca</a><br>
<a href="https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list" rel="noreferrer" target="_blank">https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list</a><br>
</div></div></blockquote></div><br></div>
</blockquote></div><br></body></html>