Re: [Chicken-users] call Chicken Scheme from C and pass a bytevector
Hum ... this has potential. struct ipv4_addr_struct { C_header tag; uint8_t *octets; }; typedef struct ipv4_addr_struct ipv4_addr; static const C_header BTREE_TAG = ((sizeof(ipv4_addr) - sizeof(C_header)) / sizeof(C_word)) | C_BYTEVECTOR_TYPE; Actually, a SRFI-4 numeric vector holds a tag (C_STRUCTURE_TYPE | 2), a pointer to a Scheme symbol and a pointer to another Scheme block, which again holds a tag (C_BYTEVECTOR_TYPE | bytecount) with the binary data directly following. This would be handled by the GC, right? No, pointers pointing outside of the Scheme heap are simply ignored by the GC. Would Scheme be able to convert or use this as a u8vector or would it be a blob which I could convert with blob-u8vector/shared ? If you build a structure like I said above, it will be a SRFI-4 XXXvector, but it might be easier to build only the blob (or bytevector). And use blob-... to convert it. blob-XXXvector will also copy it into the garbage collected heap. cheers, felix ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] call Chicken Scheme from C and pass a bytevector
Actually, the bytes should probably be allocated in the structure, right? struct ipv4_addr_struct { C_header tag; uint8_t octets[4]; }; typedef struct ipv4_addr_struct ipv4_addr; static const C_header BTREE_TAG = ((sizeof(ipv4_addr) - sizeof(C_header)) / sizeof(C_word)) | C_BYTEVECTOR_TYPE; This would be a blob (or bytevector), right. cheers, felix ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] call Chicken Scheme from C and pass a bytevector
Hi, After considering your comments (Dan Felix), reading the documents, and some experimentation, I have a solution. I decided to use atomic data. I believe the C_BYTEBLOCK_BIT is for the GC and C_BYTEVECTOR_TYPE is the scheme type. The size is in bytes because it is a byte vector, right? struct ipv4_addr_struct { C_header tag; u_int8_t octets[4]; }; typedef struct ipv4_addr_struct ipv4_addr; #define IPv4_ADDR_SIZE ( sizeof(ipv4_addr) - sizeof(C_header) ) static const C_header IPv4_ADDR_TAG = IPv4_ADDR_SIZE | C_BYTEBLOCK_BIT | C_BYTEVECTOR_TYPE; struct ipv6_addr_struct { C_header tag; u_int16_t words[8]; }; typedef struct ipv6_addr_struct ipv6_addr; #define IPv6_ADDR_SIZE ( sizeof(ipv6_addr) - sizeof(C_header) ) static const C_header IPv6_ADDR_TAG = IPv6_ADDR_SIZE | C_BYTEBLOCK_BIT | C_BYTEVECTOR_TYPE; It is used like this. There may be a better way to handle the casting. saddr_o = C_alloc( IPv4_ADDR_SIZE ); saddr_s = (ipv4_addr *)saddr_o; saddr_s-tag = IPv4_ADDR_TAG; memcpy( saddr_s-octets, saddr, sizeof(saddr) ); After that, I put it and the destination address in a regular vector along with the other packet info. The scheme packet processing code changed very little: it now uses blob-u8vector (blob-u16vector for IPv6). (define-external (process_packet (scheme-object packet)) int (let ((eth-type (vector-ref packet 0))) (case eth-type [(#x0800) ; IPv4 (let ((addr1 (blob-u8vector (vector-ref packet 1))) (addr2 (blob-u8vector (vector-ref packet 2))) (proto (vector-ref packet 3))) It has been running for a while and seems OK. More testing will follow. Thanks. -- Claude Marinier On Fri, 28 Jun 2013, Felix wrote: Actually, the bytes should probably be allocated in the structure, right? struct ipv4_addr_struct { C_header tag; uint8_t octets[4]; }; typedef struct ipv4_addr_struct ipv4_addr; static const C_header BTREE_TAG = ((sizeof(ipv4_addr) - sizeof(C_header)) / sizeof(C_word)) | C_BYTEVECTOR_TYPE; This would be a blob (or bytevector), right. cheers, felix ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] call Chicken Scheme from C and pass a bytevector
There's a section on accessing external objects that covers this sort of thing: http://wiki.call-cc.org/man/4/Accessing%20external%20objects#returning-large-objects-or-chunks-of-memory-to-scheme It's possible to allocate C structures under the control of the Chicken GC: http://wiki.call-cc.org/allocating-c-structures-under-control-of-the-chicken-gc However, you can also leave control up to the user rather than the GC and they can use free: http://api.call-cc.org/doc/lolevel/free Personally, I like to allocate blobs and srfi-4 vectors in scheme and pass them as parameters to C functions to be mutated. -Dan On 6/27/2013 10:07 AM, Claude Marinier wrote: Hi, A function in pcap-interface.c calls Chicken Scheme. It builds a vector containing a bunch of things, e.g. C_fix(ethtype), and the source and destination addresses as vectors. The scheme code converts the address vectors to u8vector (u16vector for IPv6). This is a lot of work: just under 20% of CPU time is spent in vector-u8vector. If I could create a blob in C and pass it to scheme, the scheme code could use blob-u8vector/shared and blob-u16vector/shared which would achieve the same result with much less work. What is the recommended way to pass a blob to scheme from C? Is there a way to create a u8vector or u16vector directly in C? Thank you. ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] call Chicken Scheme from C and pass a bytevector
On Thu, 27 Jun 2013, Dan Leslie wrote: There's a section on accessing external objects that covers this sort of thing: http://wiki.call-cc.org/man/4/Accessing%20external%20objects#returning-large-objects-or-chunks-of-memory-to-scheme This addresses a different issue. The PCAP event handler in C calls the packet handler in Scheme. I am looking for a way to create saddr_o and daddr_o and give them to scheme like this. vector = C_alloc( C_SIZEOF_VECTOR(7) ); vector_o = C_vector( vector, 7, C_fix(ethtype), saddr_o, daddr_o, C_fix(ip_proto), C_fix(type), C_fix(code), C_fix(tot_len) ); ret = process_packet( vector_o ); // call Scheme code It's possible to allocate C structures under the control of the Chicken GC: http://wiki.call-cc.org/allocating-c-structures-under-control-of-the-chicken-gc Hum ... this has potential. struct ipv4_addr_struct { C_header tag; uint8_t *octets; }; typedef struct ipv4_addr_struct ipv4_addr; static const C_header BTREE_TAG = ((sizeof(ipv4_addr) - sizeof(C_header)) / sizeof(C_word)) | C_BYTEVECTOR_TYPE; This would be handled by the GC, right? Would Scheme be able to convert or use this as a u8vector or would it be a blob which I could convert with blob-u8vector/shared ? However, you can also leave control up to the user rather than the GC and they can use free: http://api.call-cc.org/doc/lolevel/free I prefer to let the GC handle it. Personally, I like to allocate blobs and srfi-4 vectors in scheme and pass them as parameters to C functions to be mutated. Wrong direction: I call scheme from C. On 6/27/2013 10:07 AM, Claude Marinier wrote: Hi, A function in pcap-interface.c calls Chicken Scheme. It builds a vector containing a bunch of things, e.g. C_fix(ethtype), and the source and destination addresses as vectors. The scheme code converts the address vectors to u8vector (u16vector for IPv6). This is a lot of work: just under 20% of CPU time is spent in vector-u8vector. If I could create a blob in C and pass it to scheme, the scheme code could use blob-u8vector/shared and blob-u16vector/shared which would achieve the same result with much less work. What is the recommended way to pass a blob to scheme from C? Is there a way to create a u8vector or u16vector directly in C? Thank you. -- Claude Marinier ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users
Re: [Chicken-users] call Chicken Scheme from C and pass a bytevector
Hi, Actually, the bytes should probably be allocated in the structure, right? struct ipv4_addr_struct { C_header tag; uint8_t octets[4]; }; typedef struct ipv4_addr_struct ipv4_addr; static const C_header BTREE_TAG = ((sizeof(ipv4_addr) - sizeof(C_header)) / sizeof(C_word)) | C_BYTEVECTOR_TYPE; -- Claude Marinier On Thu, 27 Jun 2013, Claude Marinier wrote: On Thu, 27 Jun 2013, Dan Leslie wrote: There's a section on accessing external objects that covers this sort of thing: http://wiki.call-cc.org/man/4/Accessing%20external%20objects#returning-large-objects-or-chunks-of-memory-to-scheme This addresses a different issue. The PCAP event handler in C calls the packet handler in Scheme. I am looking for a way to create saddr_o and daddr_o and give them to scheme like this. vector = C_alloc( C_SIZEOF_VECTOR(7) ); vector_o = C_vector( vector, 7, C_fix(ethtype), saddr_o, daddr_o, C_fix(ip_proto), C_fix(type), C_fix(code), C_fix(tot_len) ); ret = process_packet( vector_o ); // call Scheme code It's possible to allocate C structures under the control of the Chicken GC: http://wiki.call-cc.org/allocating-c-structures-under-control-of-the-chicken-gc Hum ... this has potential. struct ipv4_addr_struct { C_header tag; uint8_t *octets; }; typedef struct ipv4_addr_struct ipv4_addr; static const C_header BTREE_TAG = ((sizeof(ipv4_addr) - sizeof(C_header)) / sizeof(C_word)) | C_BYTEVECTOR_TYPE; This would be handled by the GC, right? Would Scheme be able to convert or use this as a u8vector or would it be a blob which I could convert with blob-u8vector/shared ? However, you can also leave control up to the user rather than the GC and they can use free: http://api.call-cc.org/doc/lolevel/free I prefer to let the GC handle it. Personally, I like to allocate blobs and srfi-4 vectors in scheme and pass them as parameters to C functions to be mutated. Wrong direction: I call scheme from C. On 6/27/2013 10:07 AM, Claude Marinier wrote: Hi, A function in pcap-interface.c calls Chicken Scheme. It builds a vector containing a bunch of things, e.g. C_fix(ethtype), and the source and destination addresses as vectors. The scheme code converts the address vectors to u8vector (u16vector for IPv6). This is a lot of work: just under 20% of CPU time is spent in vector-u8vector. If I could create a blob in C and pass it to scheme, the scheme code could use blob-u8vector/shared and blob-u16vector/shared which would achieve the same result with much less work. What is the recommended way to pass a blob to scheme from C? Is there a way to create a u8vector or u16vector directly in C? Thank you. -- Claude Marinier ___ Chicken-users mailing list Chicken-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-users