f1f483c56c47d17c9030939fa756eed8ea073e26
[cl-gtk2.git] / gboxed
1 1) GBoxed - это структуры, у которых нет идентичности
2 2) При передаче ссылок, ссылки всегда имеют ограниченное время действия
3 3) Структуры могут быть открытыми и закрытыми (opaque)
4
5 Основной критерий: лисповский код не должен заботиться о владении структурами. Идентичности нет.
6
7 Следствия:
8 1) Все GBoxed, созданные в лиспе, удаляются только лиспом (при необходимости делается копия)
9 2) Если foreign-функции возвращают GBoxed, то им владеет лисп (при необходимости делается копия)
10 3) В callback'и возможна передача по ссылке (в том случае, если не знаем, как присвоить значение исходной структуре);
11 в этом случае после выхода из callback'а лисповский прокси помечается как невалидный и операции с ним приводят к исключению
12
13 Для реализации надо, чтобы CFFI позволяло совершать действия по очистке в конце callback'а.
14
15 Код:
16
17 (defclass g-boxed-type ()
18   ((g-type-designator :initarg :g-type
19                       :initform ":G-TYPE must be specified"
20                       :accessor g-boxed-type-type)))
21
22 ;;Some terminology:
23 ;; * native structure - a C structure in foreign memory that
24 ;; has the data and is expected to be passed/received by foreign functions
25 ;; * proxy - a Lisp object (class or a structure) that is
26 ;; equivalent to native structure (has the same data in it). Its lifetime is indefinite
27 ;; and it is not affected by foreign code.
28 ;; A proxy may (but not required to) contain pointer to its own copy of a
29 ;; native structure.
30 ;; * reference proxy - a proxy that is whose lifetime is equal to a duration
31 ;; of a callback. Reference proxies can only be used during a callback that created them.
32
33 ;(defgeneric create-proxy (type)
34 ;  "Creates a new proxy of a specified TYPE.")
35
36 (defgeneric create-proxy-for-native (type native-ptr)
37   (:documentation "Creates a proxy that is initialized by data contained in native
38 structured pointed to by NATIVE-PTR.
39
40 Created proxy should not be linked to NATIVE-PTR and should have
41 indefinite lifetime (until garbage collector collects it). Specifically,
42 if proxy need a pointer to native structure, it should make a copy of
43 a structure.
44
45 If proxy requires finalization, finalizers should be added."))
46
47 (defgeneric create-temporary-native (type proxy)
48   (:documentation "Creates a native structure (or passes a pointer to copy contained in PROXY)
49 that contains the same data that the PROXY contains and returns a pointer to it.
50
51 This call is always paired by call to FREE-TEMPORARY-NATIVE and calls may be nested."))
52
53 (defgeneric free-temporary-native (type proxy native-ptr)
54   (:documentation "Frees the native structure that was previously created
55 by CREATE-TEMPORARY-NATIVE for the same PROXY.
56
57 Also reads data from native structure pointer to by NATIVE-PTR
58 and sets the PROXY to contain the same data.
59
60 This call is always paired by call to CREATE-TEMPORARY-NATIVE and calls may be nested."))
61
62 (defgeneric create-reference-proxy (type native-ptr)
63   (:documentation "Creates a reference proxy for a native structure pointed to by NATIVE-PTR.
64
65 Reference proxy's lifetime is bound to duration of a callback. When the
66 callback returns the reference proxy is declared invalid and operations on it are errors.
67
68 This call is always paired by call to FREE-REFERENCE-PROXY and calls will not nest."))
69
70 (defgeneric free-reference-proxy (type proxy native-ptr)
71   (:documentation "Frees a reference proxy PROXY previously created by call to
72 CREATE-REFERENCE-PROXY. This call should ensure that all changes on PROXY are
73 reflected in native structure pointed to by NATIVE-PTR.
74
75 After a call to FREE-REFERENCE-PROXY, PROXY is declared invalid and using it is an error,
76 operations on it should signal erros.
77
78 This call is always paired by call to CREATE-REFERENCE-PROXY."))
79
80 (define-foreign-type g-boxed-foreign ()
81   ((g-type :initarg :g-type
82            :initform (error ":G-TYPE must be specified")
83            :reader g-boxed-foreign-g-type)
84    (pass-type :initarg :pass-type
85               :reader g-boxed-foreign-g-type
86               :type (member :callback :normal)
87               :initform :normal))
88   (:actual-type :pointer))
89
90 (defun g-boxed-foreign->boxed-type (type)
91   nil)
92
93 (defmethod translate-to-foreign (proxy (type g-boxed-foreign))
94   (let* ((boxed-type (g-boxed-foreign->boxed-type type))
95          (native-ptr (create-temporary-native boxed-type proxy)))
96     (values native-ptr proxy)))
97
98 (defmethod free-translated-object (native-ptr (type g-boxed-foreign) proxy)
99   (let ((boxed-type (g-boxed-foreign->boxed-type type)))
100     (free-temporary-native boxed-type proxy native-ptr)))
101
102 (defmethod translate-from-foreign (native-ptr (type g-boxed-foreign))
103   (let ((boxed-type (g-boxed-foreign->boxed-type type)))
104     (ecase )
105     (create-proxy-for-native boxed-type native-ptr)))
106