chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Chicken-users] Help with tokyocabinet, C const


From: Evan E.
Subject: [Chicken-users] Help with tokyocabinet, C const
Date: Thu, 31 Dec 2009 01:26:40 -0600

This may be beyond the scope of this mailing list, but here goes. I'm
working on extending the tokyocabinet egg to include more
functionality. It's gone well, but I'm running into an issue with one
type/procedure.

Using easyffi, I've declared the foreign type and procedure. TCMAP is
a hash map struct, tcmapget returns a value for a given key from the
map object:

___declare(type, "MAP;(nonnull-c-pointer \"TCMAP\");tc-map-ptr")
const void *tcmapget(MAP map, ___scheme_pointer kbuf, int ksiz, ___pointer int *sp);

Based on the example of the original egg, I've created the scheme
function tc-map-get to return a string value by calling the procedure
tcmapget. (Source code below.) Here's what happens when I try to use
tc-map-get on a tc-map type:

#;1> (tc-map-get atcmap "key")
"value"
#;2> (tc-map-get atcmap "key")
csi(3208) malloc: *** error for object 0x111360: double free
*** set a breakpoint in malloc_error_break to debug
"value"

I assume the issue has something to do with the function
sized-c-string*, which is used by tc-map-get to create strings from
the pointers returned by Tokyo Cabinet.

A number of other procedures in Tokyo Cabinet return a pointer to the
region of a value, and sized-c-string* works without issue when
applied to these "get" procedures. tcmapget is unique in that it
returns a pointer to a constant, while the other "get" procedures just
return a pointer.

I've been stumped by this for a while -- my knowledge of C is
minimal. Is there a direction I should go? Can I re-write the
sized-c-string* function to account for the possibility of a constant?
Is there something I can change in the ffi declaration? Any help would
be greatly, greatly appreciated.

Evan

*** source ***

(declare
  (foreign-declare "

#define copy_string_result(ptr, len, str) (C_memcpy(C_c_string(str), (char *)C_block_item(ptr, 0), C_unfix(len)), C_SCHEME_UNDEFINED)

"))

(define-foreign-variable +max-string-length+ int "C_HEADER_SIZE_MASK")

;; Copy size bytes from ptr into new string and free ptr.
;; Like c-string* return type but does not use null terminator.
;; Note: Exception handling imposes an unacceptable overhead.
(define (sized-c-string* ptr size #!optional (where 'sized-c-string*))
  (when (> size +max-string-length+)
    (free ptr)
    (error where "string length too long" size))
  (let ((val (make-string size)))
    (##core#inline "copy_string_result" ptr size val)
    (free ptr)
    val))


(define (tc-map-get tc-map key)
  (let-location ((size int))
    (and-let* ((ptr (%tc-map-get tc-map key
                                 (string-length key) (location size))))
      (sized-c-string* ptr size 'tc-map-get))))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]