diff options
| author | Mike Pall <mike> | 2011-04-12 19:15:00 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2011-04-12 19:16:39 +0200 |
| commit | 3b6f37dd2c336987251d53a4678396ef38921b3e (patch) | |
| tree | 6e6176c37b600e461d078dbe663008dcc84d2418 /doc/ext_ffi_tutorial.html | |
| parent | fa5cd010e8e28c7fe2338d0fdd538e95ddd88bcc (diff) | |
| download | luajit-3b6f37dd2c336987251d53a4678396ef38921b3e.tar.gz luajit-3b6f37dd2c336987251d53a4678396ef38921b3e.tar.bz2 luajit-3b6f37dd2c336987251d53a4678396ef38921b3e.zip | |
FFI: Add ctype metamethods and ffi.metatype().
Diffstat (limited to 'doc/ext_ffi_tutorial.html')
| -rw-r--r-- | doc/ext_ffi_tutorial.html | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/doc/ext_ffi_tutorial.html b/doc/ext_ffi_tutorial.html index 38126865..d5b04bc6 100644 --- a/doc/ext_ffi_tutorial.html +++ b/doc/ext_ffi_tutorial.html | |||
| @@ -386,6 +386,99 @@ application might work on some systems, but would fail in a POSIX/x64 | |||
| 386 | environment. | 386 | environment. |
| 387 | </p> | 387 | </p> |
| 388 | 388 | ||
| 389 | <h2 id="metatype">Defining Metamethods for a C Type</h2> | ||
| 390 | <p> | ||
| 391 | The following code explains how to define metamethods for a C type. | ||
| 392 | We define a simple point type and add some operations to it: | ||
| 393 | </p> | ||
| 394 | <pre class="code mark"> | ||
| 395 | <span class="codemark"> | ||
| 396 | ① | ||
| 397 | |||
| 398 | |||
| 399 | |||
| 400 | ② | ||
| 401 | |||
| 402 | ③ | ||
| 403 | |||
| 404 | ④ | ||
| 405 | |||
| 406 | |||
| 407 | |||
| 408 | ⑤ | ||
| 409 | |||
| 410 | ⑥</span>local ffi = require("ffi") | ||
| 411 | ffi.cdef[[ | ||
| 412 | <span style="color:#00a000;">typedef struct { double x, y; } point_t;</span> | ||
| 413 | ]] | ||
| 414 | |||
| 415 | local point | ||
| 416 | local mt = { | ||
| 417 | __add = function(a, b) return point(a.x+b.x, a.y+b.y) end, | ||
| 418 | __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end, | ||
| 419 | __index = { | ||
| 420 | area = function(a) return a.x*a.x + a.y*a.y end, | ||
| 421 | }, | ||
| 422 | } | ||
| 423 | point = ffi.metatype("point_t", mt) | ||
| 424 | |||
| 425 | local a = point(3, 4) | ||
| 426 | print(a.x, a.y) --> 3 4 | ||
| 427 | print(#a) --> 5 | ||
| 428 | print(a:area()) --> 25 | ||
| 429 | local b = a + point(0.5, 8) | ||
| 430 | print(#b) --> 12.5 | ||
| 431 | </pre> | ||
| 432 | <p> | ||
| 433 | Here's the step-by-step explanation: | ||
| 434 | </p> | ||
| 435 | <p> | ||
| 436 | <span class="mark">①</span> This defines the C type for a | ||
| 437 | two-dimensional point object. | ||
| 438 | </p> | ||
| 439 | <p> | ||
| 440 | <span class="mark">②</span> We have to declare the variable | ||
| 441 | holding the point constructor first, because it's used inside of a | ||
| 442 | metamethod. | ||
| 443 | </p> | ||
| 444 | <p> | ||
| 445 | <span class="mark">③</span> Let's define an <tt>__add</tt> | ||
| 446 | metamethod which adds the coordinates of two points and creates a new | ||
| 447 | point object. For simplicity, this function assumes that both arguments | ||
| 448 | are points. But it could be any mix of objects, if at least one operand | ||
| 449 | is of the required type (e.g. adding a point plus a number or vice | ||
| 450 | versa). Our <tt>__len</tt> metamethod returns the distance of a point to | ||
| 451 | the origin. | ||
| 452 | </p> | ||
| 453 | <p> | ||
| 454 | <span class="mark">④</span> If we run out of operators, we can | ||
| 455 | define named methods, too. Here the <tt>__index</tt> table defines an | ||
| 456 | <tt>area</tt> function. For custom indexing needs, one might want to | ||
| 457 | define <tt>__index</tt> and <tt>__newindex</tt> functions instead. | ||
| 458 | </p> | ||
| 459 | <p> | ||
| 460 | <span class="mark">⑤</span> This associates the metamethods with | ||
| 461 | our C type. This only needs to be done once. For convenience, a | ||
| 462 | constructor is returned by | ||
| 463 | <a href="ffi_ext_api.html#ffi_metatype"><tt>ffi.metatype()</tt></a>. | ||
| 464 | We're not required to use it, though. The original C type can still | ||
| 465 | be used e.g. to create an array of points. The metamethods automatically | ||
| 466 | apply to any and all uses of this type. | ||
| 467 | </p> | ||
| 468 | <p> | ||
| 469 | Please note that the association with a metatable is permanent and | ||
| 470 | <b>the metatable must not be modified afterwards!</b> Ditto for the | ||
| 471 | <tt>__index</tt> table. | ||
| 472 | </p> | ||
| 473 | <p> | ||
| 474 | <span class="mark">⑥</span> Here are some simple usage examples | ||
| 475 | for the point type and their expected results. The pre-defined | ||
| 476 | operations (such as <tt>a.x</tt>) can be freely mixed with the newly | ||
| 477 | defined metamethods. Note that <tt>area</tt> is a method and must be | ||
| 478 | called with the Lua syntax for methods: <tt>a:area()</tt>, not | ||
| 479 | <tt>a.area()</tt>. | ||
| 480 | </p> | ||
| 481 | |||
| 389 | <h2 id="idioms">Translating C Idioms</h2> | 482 | <h2 id="idioms">Translating C Idioms</h2> |
| 390 | <p> | 483 | <p> |
| 391 | Here's a list of common C idioms and their translation to the | 484 | Here's a list of common C idioms and their translation to the |
