2012-02-21 94 views
3

我有寫在優化的C(LIBRARY.C)一個複雜的文庫:傳和接收字符串

#include <stdio.h> 
#include "library.h" 

void make_fullname(char* fullname, char* name, int version) { 
    sprintf(fullname, "%s-%d", name, version); 
    printf("lib-name: %s\n", name); 
    printf("lib-fullname: %s\n", fullname); 
} 

其中library.h包含

void make_fullname(char* fullname, char* name, int version); 

該庫被編譯如下:

gcc library.c -o library.so -shared 

我試圖利用它從SBCL,這裏是我最後拿(關於這一點我放棄了,轉而ST一ackoverflow):

(load-shared-object "library.so") 

(define-alien-routine make_fullname void 
    (fullname (c-string :external-format :ascii)) 
    (name (c-string :external-format :ascii)) 
    (x int)) 


(defun print-name-version (name version) 
    (with-alien ((fullname (c-string :external-format :ascii))) 
    (setf fullname (make-alien char 100)) 
    (setf fullname "dummy-string") 
    (make_fullname fullname name version) 
    (format t "~a~%" fullname))) 

一旦運行,例如,(打印名稱版 「計劃」 1)我得到這個

lib-name: Program 
lib-fullname: Program-1 
dummy-string 
NIL 

所以,一切正常,除了傳遞字符串回口齒不清。這個例子裏有什麼不妥?謝謝,安德烈。

更新我有我的lisp代碼工作,但我仍然不明白爲什麼原始代碼段失敗。這裏是一個正在運行的:

(defun print-name-version (name version) 
    (let ((fullname (make-alien char 100))) 
    (make_fullname fullname name version) 
    (with-alien ((fn-str-repr (c-string :external-format :ascii) fullname)) 
     (format t "~a~%" fn-str-repr)) 
    (free-alien fullname))) 
+0

僅僅是一個信息點:如果make_fullname的調用者沒有爲格式化的字符串提供足夠的存儲空間,那麼您可能需要記住這一點,即在此處可能存在緩衝區溢出。我也假定這個代碼只是作爲一個例子,而不是你的「複雜的圖書館」?因爲在後一種情況下,你知道你可以做'(defun make-version(name version)(format nil「〜a-〜d」name version))',對嗎? :) – lindes 2012-02-22 17:27:47

+0

當然:),這些只是一些嘗試,以熟悉ffi。 – Andrei 2012-03-04 23:13:42

回答

6

我從來沒有使用SBCL本地FFI綁定,但我想我想通了。爲了將來參考,您將更有可能獲得關於CFFI的幫助,而不是實現特定的FFI綁定。

從Lisp代碼訪問時,外來類型c字符串的變量會自動轉換爲Lisp字符串。頂級函數make_fullname是Lisp代碼,它依次調用外來例程,但到那時fullname已被轉換爲Lisp字符串,然後轉換爲新的 c字符串,一旦調用完成,該字符串將被丟棄。

您需要在編輯過程中做些什麼:分配存儲緩衝區並將其傳遞給外來函數,並將關聯的c-string變量視爲該存儲上的Lisp視圖。

+0

感謝您解決這個難題(並提及CFFI,我是lisp的新手,這是我第一次看到這個鏈接:) – Andrei 2012-02-22 08:37:22