Re: [Chicken-users] call Chicken Scheme from C and pass a bytevector

2013-06-28 Thread Felix
 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

2013-06-28 Thread Felix
 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

2013-06-28 Thread Claude Marinier

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

2013-06-27 Thread Dan Leslie
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

2013-06-27 Thread Claude Marinier


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

2013-06-27 Thread Claude Marinier

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