Передача и получение строк с SBCL FFI - PullRequest
3 голосов
/ 21 февраля 2012

У меня сложная библиотека, написанная на оптимизированном 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, вот мой последний дубль (тот, на котором я сдаюсь и обращаюсь к stackoverflow):

(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)))

После запуска, например, (print-name-version "Program" 1) Я получаю это

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

Итак, все работает, кроме передачи строки обратно в lisp.Что не так в этом примере?Спасибо, Андрей.

Обновление Мой код 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)))

1 Ответ

6 голосов
/ 22 февраля 2012

Я никогда не использовал родные привязки FBC SBCL, но, думаю, я понял это. Для дальнейшего использования вы, скорее всего, получите справку о CFFI , а не о привязках FFI для конкретной реализации.

Переменные c-строки инопланетного типа автоматически преобразуются в строки Lisp при доступе из кода Lisp. Функция верхнего уровня make_fullname - это код на Лиспе, который, в свою очередь, вызывает инопланетную процедуру, но к этому времени fullname был преобразован в строку на Лиспе, которая затем преобразуется в новую c-строку , который сбрасывается после завершения вызова.

Вам нужно сделать то, что вы делали в редактировании: выделить буфер хранения и передать его в чужую функцию, и обработать связанную переменную c-string как представление Lisp в этом хранилище.

...