C-FFI pointers in c function arguments
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 ;;;------------------------------------------------
participants (2)
-
Marc Feeley -
Sid H