Hi,
I'm just starting with the FFI. I'm trying to call a C function that updates a pointer argument. However, that value does not seem to change.
My understanding is that all arguments passed to C are treated as immutable. So, if we need to return any value from C then, it cannot be via an argument only. Is that correct? Please see my example below.
(c-declare #<<c-declare-end
#include <stdio.h>
int get_value(int* value) { if(NULL != value) { *value = 42; } else { printf("Invalid pointer"); }
return 21; }
c-declare-end )
(c-define-type int* (pointer int))
(define get-value (c-lambda (int*) int "get_value"))
;; Define a Wrapper in C (define %get-value (c-lambda () int #<<C-END int tmp; int retval = get_value(&tmp);
/* TODO: Handle retval inside the C Wrapper code */
___result = tmp; C-END ))
;; Can we update a pointer via a c function call arg? (define value #f) (let ((retval (get-value value))) (if (eq? retval 21) (begin (display value) ; Prints #f (newline)) (begin (display "Did not get 21 as return value") (newline))))
; Now use the wrapper API instead (set! value (%get-value)) (display value) ; No surprise, prints 42 (newline)
Thanks, Sid
Afficher les réponses par date
On 2010-11-19, at 3:06 AM, Sid H wrote:
Hi,
I'm just starting with the FFI. I'm trying to call a C function that updates a pointer argument. However, that value does not seem to change.
My understanding is that all arguments passed to C are treated as immutable. So, if we need to return any value from C then, it cannot be via an argument only. Is that correct? Please see my example below. ...
You are not obeying the API of the get_value function, which expects an int* parameter. You need to supply a pointer to a C allocated "int". Here's how I would do it.
Marc
;;;------------------------------------------------
;; Functions on int* type.
(c-declare #<<c-declare-end
#include <stdlib.h>
int *new_int() { printf("new_int\n"); return (int*)malloc(sizeof(int)); }
___SCMOBJ free_int(void *ptr) { printf("free_int\n"); free(ptr); return ___NO_ERR; }
int get_int(int *ptr) { return *ptr; } void set_int(int *ptr, int val) { *ptr = val; }
c-declare-end )
(c-define-type int* (nonnull-pointer int (int*))) (c-define-type int*/free (nonnull-pointer int (int*) "free_int"))
(define new-int (c-lambda () int*/free "new_int")) (define get-int (c-lambda (int*) int "get_int")) (define set-int (c-lambda (int* int) void "set_int"))
(define (test) (let ((p (new-int))) (set-int p 123) (pp (get-int p)) (set-int p 999) (pp (get-int p)) (set! p 'foo) (##gc))) ;; object allocated by new-int will be freed
;;;------------------------------------------------
(c-declare #<<c-declare-end
#include <stdio.h>
int get_value(int* value) { *value = 42;
return 21; }
c-declare-end )
(define get-value (c-lambda (int*) int "get_value"))
(define value (new-int))
(set-int value 99999)
(println (get-int value))
(let ((retval (get-value value))) (if (= retval 21) (println value) (println "Did not get 21 as return value")))
(println (get-int value))
;; will print: ;; ;; new_int ;; 99999 ;; #<int* #2 0x100502740> ;; 42 ;; free_int
;;;------------------------------------------------