From 3b6f37dd2c336987251d53a4678396ef38921b3e Mon Sep 17 00:00:00 2001
From: Mike Pall
+Creates a ctype object for the given ct and associates it with +a metatable. Only struct/union types, complex numbers +and vectors are allowed. Other types may be wrapped in a +struct, if needed. +
++The association with a metatable is permanent and cannot be changed +afterwards. Neither the contents of the metatable nor the +contents of an __index table (if any) may be modified +afterwards. The associated metatable automatically applies to all uses +of this type, no matter how the objects are created or where they +originate from. Note that pre-defined operations on types have +precedence (e.g. declared field names cannot be overriden). +
++All standard Lua metamethods are implemented. These are called directly, +without shortcuts and on any mix of types. For binary operations, the +left operand is checked first for a valid ctype metamethod. The +__gc metamethod only applies to struct/union +types and performs an implicit ffi.gc() +call during creation of an instance. +
+Associates a finalizer with a pointer or aggregate cdata object. The diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index f9a118a0..d9aa27c8 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html @@ -582,6 +582,10 @@ Reference types are dereferenced before performing each of the operations below — the operation is applied to the C type pointed to by the reference.
++The pre-defined operations are always tried first before deferring to a +metamethod for a ctype (if defined). +
Memory areas returned by C functions (e.g. from malloc()) -must be manually managed, of course. Pointers to cdata objects are -indistinguishable from pointers returned by C functions (which is one -of the reasons why the GC cannot follow them). +must be manually managed, of course (or use +ffi.gc())). Pointers to +cdata objects are indistinguishable from pointers returned by C +functions (which is one of the reasons why the GC cannot follow them).
+The following code explains how to define metamethods for a C type. +We define a simple point type and add some operations to it: +
++ +① + + + +② + +③ + +④ + + + +⑤ + +⑥local ffi = require("ffi") +ffi.cdef[[ +typedef struct { double x, y; } point_t; +]] + +local point +local mt = { + __add = function(a, b) return point(a.x+b.x, a.y+b.y) end, + __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end, + __index = { + area = function(a) return a.x*a.x + a.y*a.y end, + }, +} +point = ffi.metatype("point_t", mt) + +local a = point(3, 4) +print(a.x, a.y) --> 3 4 +print(#a) --> 5 +print(a:area()) --> 25 +local b = a + point(0.5, 8) +print(#b) --> 12.5 ++
+Here's the step-by-step explanation: +
++① This defines the C type for a +two-dimensional point object. +
++② We have to declare the variable +holding the point constructor first, because it's used inside of a +metamethod. +
++③ Let's define an __add +metamethod which adds the coordinates of two points and creates a new +point object. For simplicity, this function assumes that both arguments +are points. But it could be any mix of objects, if at least one operand +is of the required type (e.g. adding a point plus a number or vice +versa). Our __len metamethod returns the distance of a point to +the origin. +
++④ If we run out of operators, we can +define named methods, too. Here the __index table defines an +area function. For custom indexing needs, one might want to +define __index and __newindex functions instead. +
++⑤ This associates the metamethods with +our C type. This only needs to be done once. For convenience, a +constructor is returned by +ffi.metatype(). +We're not required to use it, though. The original C type can still +be used e.g. to create an array of points. The metamethods automatically +apply to any and all uses of this type. +
++Please note that the association with a metatable is permanent and +the metatable must not be modified afterwards! Ditto for the +__index table. +
++⑥ Here are some simple usage examples +for the point type and their expected results. The pre-defined +operations (such as a.x) can be freely mixed with the newly +defined metamethods. Note that area is a method and must be +called with the Lua syntax for methods: a:area(), not +a.area(). +
+Here's a list of common C idioms and their translation to the -- cgit v1.2.3-55-g6feb