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