<div>Taylor,</div><div><br></div><div>The code attached at the bottom does what you want, without need for linking to os_io.c . In case Gambit would change it might need update.</div><div><br></div><div>Mikael</div><br><div class="gmail_quote">
2010/1/17 Taylor Venable <span dir="ltr"><<a href="mailto:taylor@metasyntax.net">taylor@metasyntax.net</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Hi, I've been hacking a lot the last couple days to try to figure out<br>
how to get the file descriptor for a socket created with open-tcp-client<br>
on Linux.  I've finally got it figured out, and to do it I obtain the<br>
rdevice for the port via the condition variable and in C cast it to a<br>
___device_tcp_client_struct to extract the 's' field (the file descrip-<br>
tor).  There's only one problem: whereas ___device_stream_struct is<br>
defined in os_io.h and I can conveniently include it from my C code, the<br>
definition of ___device_tcp_client_struct is in os_io.c and I had to<br>
copy it out and paste it into my code.  Is there something about that<br>
definition that makes its location in the C source (rather than the<br>
header) necessary?  I'd prefer to just #include something, but if the<br>
only way is to copy/paste those lines then I'll just continue to do<br>
that.  Thanks for any advice.<br>
<font color="#888888"><br>
--<br>
Taylor Venable<br>
<a href="http://metasyntax.net/" target="_blank">http://metasyntax.net/</a><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" target="_blank">https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list</a><br>
</font></blockquote></div><br><div><br></div><div> - </div><div><br></div><div><br></div><div><div>(c-declare "</div><div>#include <unistd.h></div><div>#include <errno.h></div><div>#include <string.h></div>
<div>#include <fcntl.h></div><div>#include </usr/local/Gambit-C/current/lib/os_io.h> // I'm well aware this is not the default installation directory for this file.</div><div>                                                   // Though let's use it for convention. Requires os.h and os_time.h .</div>
<div>")</div><div><br></div><div><br></div><div>; How to get file descriptor of TCP socket port:</div><div>; ##make-device-port on _io.scm 1202 puts its rdevice and wdevice parameters</div><div>; as condition-variable-name of ##vector-ref 44 and 45 of the port.</div>
<div>; ##make-device-port is invoked by ##make-device-port-from-single-device of row 1560,</div><div>; which is in turn invoked by ##make-tcp-client-port 5767, which is in turn invoked</div><div>; by ##open-tcp-client on row 5816. Please note that rdevice and wdevice are the</div>
<div>; same variable. It is generated by ##os-device-tcp-client-open invoked on</div><div>; row 5807, that's declared in _kernel.scm row 3966, which calls ___os_device_tcp_client_open</div><div>; that's declared in os_io.c row 7272. So the return value contains this.</div>
<div>; The return value is generated by ___NONNULLPOINTER_to_SCMOBJ (defined in c_intf.c 4617) that convers an arbitrary pointer</div><div>; to a SCMOBJ. In this case it's the ___device_tcp_client structure dev.</div>
<div>;</div><div>; The socket (i.e. the file descriptor) is generated by a call to the OS function socket</div><div>; on row 3407 in the function create_tcp_socket. The result is written to the SOCKET_TYPE</div><div>; pointer argument that's the first parameter of the function. The function is called by</div>
<div>; ___device_tcp_client_setup_from_sockaddr declared on row 3559. After generation it passes</div><div>; the socket into ___device_tcp_client_setup_from_socket declared on row 3472, as third parameter.</div><div>; As first parameter, the function takes the ___device_tcp_client. It copies the socket into the ->s</div>
<div>; property of the structure.</div><div>;</div><div>; ___device_tcp_client is declared on row 2960 in os_io.c . The structure is designed like that first</div><div>; in it, there's a ___device_stream, then the socket comes. ___device_stream is defined in os_io.h row 414.</div>
<div>; SOCKET_TYPE is declared in os_io.c and is defined to int on USE_POSIX systems, and to SOCKET on USE_WIN32</div><div>; systems.</div><div>;</div><div>; Thus, to get the socket file descriptor of an open TCP socket port, take the int sizeof(___device_stream)</div>
<div>; bytes into (condition-variable-name (##vector-ref port 44)) .</div><div>;</div><div>; ** In case this function stops working with a new version of Gambit,</div><div>; ** First check if the ___device_tcp_client structure has been changed, that is, if the first property is not</div>
<div>; ** a ___device_stream and the second the socket anymore.</div><div>; ** Second, check if the name parameter of vector-index no. 44 of TCP connection ports aren't</div><div>; ** (see macro-device-port-rdevice-condvar's definition)</div>
<div>; ** foreign-objects in general, and ___device_tcp_client values in particular, anymore. Use (##vector->list port). </div><div><br></div><div>(define (tcp-socket-port->fd port)</div><div>  (let* ((___device_tcp_client (condition-variable-name (util#device-port-rdevice-condvar port)))</div>
<div>         (ptr (foreign-address ___device_tcp_client)))</div><div>    ((c-lambda (unsigned-long) int #<<C</div><div>       int ptrv = ___arg1;</div><div>       // fprintf(stderr,"In C now, the pointer value is %i. sizeof(___device_stream) is %i.\n\n",ptrv,sizeof(___device_stream));</div>
<div>       // ___device_stream* v = ___CAST(___device_stream*,(int*) ptrv);</div><div>       // fprintf(stderr,"v is %i.\n",(int) v);</div><div>       ptrv += sizeof(___device_stream);</div><div>       int* ptr = (int*) ptrv;</div>
<div>       // fprintf(stderr,"In C now, after having added to the pointer, it's %i (%i). The value found at its location is %i.\n\n",(int) ptr,ptrv,*ptr);</div><div>       ___result = *ptr;</div><div>C</div>
<div>               ) ptr)))</div><div><br></div></div>