Hello! I've encountered some behavior in C-FFI that I would like to discuss. When you try to define an enumeration containing duplicate values, C-FFI gives the error:
"A foreign enum cannot contain duplicate values: 0."
However, C enumerations can contain duplicate values, and this feature is used by real code. FLTK, for example, uses it to provide for source compatibility when the name of enumeration elements are changed. Without direct C-FFI support for this feature, the resultant C-FFI bindings do not translate well to what the user expects (enumeration keys available in the C header are not available in the Lisp binding).
Verrazano works around this issue right now (by discarding duplicate keys), but it's a sub-optimal solution, since there is no way to programatically determine a consistent set of keys to discard. For example, FLTK contains an enumeration in which FL_ALIGN_TOP_LEFT and FL_ALIGN_LEFT_TOP alias each other, and FL_ALIGN_TOP_RIGHT FL_ALIGN_RIGHT_TOP alias each other. Depending on the ordering in the header file, the enumeration may end up containing an inconsistent set of names (eg: FL_ALIGN_TOP_LEFT and FL_ALIGN_RIGHT_TOP).
Sincerely, Rayiner Hashem
On 2/set/2005, at 00:28, Rayiner Hashem wrote:
Hello! I've encountered some behavior in C-FFI that I would like to discuss. When you try to define an enumeration containing duplicate values, C-FFI gives the error:
"A foreign enum cannot contain duplicate values: 0."
However, C enumerations can contain duplicate values, and this feature is used by real code.
My bad. When adding that check I wondered if duplicate values would make sense, IIRC I probably let the check in because I wondered about what to do in this case:
(defcenum foo (:a 0) (:b 0))
When for example some function with FOO as a return type returns 0, what keyword should 0 be translated to? :A or :B?
CLISP warns and uses the last value: [this is what James's tree does iirc, except it doesn't warn]
[1]> (ffi:def-c-enum foo (a 0) (b 0)) WARNING: FFI:DEF-C-ENUM (FOO): value 0 will be assigned to both A and B FOO [2]> (ffi:enum-from-value 'foo 0) B
CMUCL and SBCL throw an error:
Error in function PARSE-ENUM: Element value 0 used more than once. [Condition of type SIMPLE-ERROR]
Lispworks doesn't warn and uses the first:
CL-USER 1 > (fli:define-c-enum foo (a 0) (b 0)) (:ENUM FOO)
CL-USER 2 > (fli:enum-value-symbol 'foo 0) A
Any suggestions?