{"id":13803719,"url":"https://github.com/rpav/cl-autowrap","last_synced_at":"2025-05-13T16:32:24.609Z","repository":{"id":9608468,"uuid":"11532046","full_name":"rpav/cl-autowrap","owner":"rpav","description":"(c-include \"file.h\") =\u003e complete FFI wrapper","archived":false,"fork":false,"pushed_at":"2024-06-02T03:33:33.000Z","size":311,"stargazers_count":218,"open_issues_count":37,"forks_count":41,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-11-18T20:48:53.226Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rpav.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-07-19T16:24:47.000Z","updated_at":"2024-11-09T02:58:04.000Z","dependencies_parsed_at":"2024-11-19T05:52:48.766Z","dependency_job_id":null,"html_url":"https://github.com/rpav/cl-autowrap","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rpav%2Fcl-autowrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rpav%2Fcl-autowrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rpav%2Fcl-autowrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rpav%2Fcl-autowrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rpav","download_url":"https://codeload.github.com/rpav/cl-autowrap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253981913,"owners_count":21994354,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T01:00:37.260Z","updated_at":"2025-05-13T16:32:19.594Z","avatar_url":"https://github.com/rpav.png","language":"Python","funding_links":[],"categories":["C ##"],"sub_categories":[],"readme":"# Now with libffi!\n\nUsing its own facilities, autowrap now includes `autowrap/libffi`.\nThis allows functions that pass and return structs to be called using\nautowrap.  To use this, just load or `:depends-on`\n`cl-autowrap/libffi` instead of `cl-autowrap`:\n\n```lisp\n\n  :depends-on (... :cl-autowrap/libffi ...)\n  ...\n```\n\nOf course, this requires `libffi` be compiled and available to your\nlisp.\n\nUsage mostly identical; functions called via libffi look and act the\nsame as any others.  The one exception is functions that *return* a\nstruct by value:\n\n```lisp\n(c-with ((return-value some-struct))\n  (some-call-returning-some-struct return-value ...))\n```\n\nCalls returning a struct take the return as their first parameter.\nThis should be evident in SLIME/Sly.  This ultimately allows easier\nmanagement of freeing as well as more control over where they're\nstored.  (They *also* still return the value, if you're trying to\nchain calls.)\n\n\n# Issues?\n\nIf you have issues, do not hesitate to [file an\nissue](https://github.com/rpav/cl-autowrap/issues/new)!  **See [the\nFAQ](https://github.com/rpav/cl-autowrap/blob/master/FAQ.md)\nfor some quick tips.**\n\n# cl-autowrap\n\nThis is a new [c2ffi](https://github.com/rpav/c2ffi)-based wrapper\ngenerator for Common Lisp with a focus, performance, convenience, and\ncompleteness.  It works like this:\n\n```lisp\n(c-include \"file.h\")\n```\n\nThat's it.  This calls `c2ffi` and generates architecture-specific\n`.spec` files you can distribute with your project.  **Neither c2ffi,\nnor any compiler (or even `.h` files!) are necessary for your users!**\n\n* Types: structs (including bitfields!), unions, enums, typedefs, etc.\n* Wrappers: Thin wrappers for structs, unions, and aliases of structs\n  and unions: pointers and validation only, no expensive translation\n* Accessors: Complete recursive accessors for structs and unions,\n  including anonymous struct members, arrays, and pointers for each\n  field.\n* Functions: Macros which expand into foreign calls via CFFI-SYS\n* Metadata: Full access to all the information about all types,\n  functions, etc.\n\nFor instance:\n\n```c\n/* test.h - abbreviated from example */\ntypedef struct foo {\n  int a, b;\n  char c[3];\n\n  struct {\n    unsigned int b0 : 2, b1 : 3;\n\n    struct {\n      char x, y;\n    } s;\n  } x[2];\n} foo_t;\n\nfoo_t* get_foo();\nvoid free_foo(foo_t *foo);\nint* get_int();\n```\n\nOut of this, we can do the following.  (Note: dots are just part of\nthe function names for disambiguation, this doesn't alter the reader):\n\n```lisp\n(c-include \"test.h\")\n\n(let ((foo (get-foo)))\n  (setf (foo-t.a foo) 5)             ;; foo.a = 5;\n  (setf (foo-t.x[].b0 foo 0) #b10)   ;; foo.x[0].b0 = 2;\n  (print (foo-t.x[].s.x foo 1))      ;; anonymous struct\n  (foo-t.x[].s foo 0)                ;; =\u003e child wrapper\n  (foo-t.x[].s\u0026 foo 0)               ;; \u0026(foo.x[0].s) =\u003e pointer\n  (free-foo foo))\n```\n\nAlternatively, there is now `cl-plus-c`, which can optionally be\nloaded for a different access mechanism and **much quicker compile\ntimes**:\n\n```lisp\n(asdf:load-system :cl-plus-c)\n(use-package :plus-c)\n\n;;; This allocates a FOO-T and frees it at the end:\n(c-let ((foo foo-t :free t))\n  (print foo)                        ;; =\u003e wrapper\n  (setf (foo :a) 5)                  ;; foo.a = 5;\n  (setf (foo :x 0 :b0) #b10)         ;; foo.x[0].b0 = 2;\n  (print (foo :x 1 :s :x))           ;; anonymous struct: foo.x[1].s.x\n  (foo :x 0 :s)                      ;; =\u003e child wrapper\n  (foo :x 0 :s \u0026))                   ;; \u0026(foo.x[0].s) =\u003e pointer\n```\n\nSee\n[cl-plus-c.md](https://github.com/rpav/cl-autowrap/blob/master/cl-plus-c.md)\nfor more information.\n\n## Overview\n\nUsing `cl-autowrap` is meant to get you to the \"lispifying\" stage of\nyour wrapper as quickly and conveniently as possible:\n\n* Make sure you have c2ffi\n* Load your library as you normally would with CFFI\n* Make a file for your `c-include`\n* Examine wrappers and tweak if necessary\n* Back to lisp!\n\n### c2ffi\n\nYou will need to build [c2ffi](https://github.com/rpav/c2ffi) if you\nhave not already done so.  This requires a repository version of LLVM\nand Clang, but the build process is straightforward.\n\nAgain, note that **your users do not need this**, assuming you\ndistribute the `.spec` files appropriate to their architecture.\n`cl-autowrap` should generate everything for you, though.\n\nIf you decide not to install `c2ffi`, you can specify its path\ndirectly by setting `autowrap:*c2ffi-program*`, e.g.:\n\n```lisp\n(setf autowrap:*c2ffi-program* \"/path/to/my/c2ffi\")\n```\n\nThis should be part of *your local configuration*; do not set this in\ncode you distribute.  This includes `LET` forms around `C-INCLUDE`.\n\n### Loading Libraries\n\nThis should be done normally with CFFI.  Either the high-level\ninterface with `CFFI:DEFINE-FOREIGN-LIBRARY` and\n`CFFI:USE-FOREIGN-LIBRARY` or the low-level interface with\n`CFFI-SYS:%LOAD-FOREIGN-LIBRARY` work.\n\n### Writing the `c-include`\n\nIt's highly recommended that you use a separate package *and* file for\n`cl-autowrap`.  The reasons are simple:\n\n* A *lot* of symbols will be generated without regard.\n* Many symbols will also be exported.\n* A rather large number of functions and structs will be generated,\n  resulting in a hefty compile time.  With a separate file, this only\n  needs to happen once.\n\n(In fact, you can now specify individual packages for each set of\nsymbols that are generated.  See below.)\n\nOnce you have this, you can write a simple `c-include`.  **This must\nbe a top-level statement**:\n\n```lisp\n(c-include \"somefile.h\")\n```\n\nThis will look for `somefile.h` and generate `.spec` files in\n`*default-pathname-defaults*`, which is probably not very helpful!  To\nfix this, use the following:\n\n```lisp\n(c-include (function-that-finds \"somefile.h\")\n           :spec-path #P\"/path/to/spec\")\n```\n\n(Note that while these parameters *are* `eval`'d, this happens at\n*compile time*, so if you use a `*special-variable*`, its definition\nneeds surrounded by an `EVAL-WHEN`.)\n\nHardcoded paths and reinventing functionality aren't very nice though;\nIn both cases you can specify a complete \"ASDF path\" (starting with\nthe system name), and it'll query the path from ASDF.  For example, if\nwe have an ASDF system called `my-wrapper`, we can do the following:\n\n```lisp\n(c-include '(my-wrapper some-module \"localfile.h\")\n           :spec-path '(my-wrapper spec-module))\n```\n\nAssuming you had defined \"localfile.h\" as a `:static-file` of\n`some-module` in `my-wrapper`, as well as `spec-module`, everything\nwould work as intended.\n\nThis is especially useful because you can have a single local header\nthat includes all the files you wish to wrap, and those will be found\nby `c2ffi` in the standard include paths.\n\n### Tweaking\n\nWhile `c2ffi` and `cl-autowrap` do quite a lot, there are a few times\nwhere you may want to or be required to intervene.  You can look at\nany errors that occur, or the symbols that are exported, or even\nsimply macroexpand the `c-include` and examine the output.\n\nBy default, `c2ffi` outputs *everything* and likewise `cl-autowrap`\nimports *everything*.  Thus you get a rather large sampling of libc\nwhere you probably don't need it.  Thus you may want to *exclude* some\ndefinitions.  You can do this in two ways:\n\n```lisp\n(c-include \"file.h\"\n           :exclude-sources (\"/path/to/source1\"\n                             \"/path/.*source2\" ...)\n           :exclude-definitions (\"SomeFunc1\"\n                                 \"_suffix$\"))\n```\n\nThe first, `:exclude-sources`, looks at the source information\ngenerated by `c2ffi` for each definition.  This is an easy way to\nexclude the majority of irrelevant definitions.  You can make\nexceptions to this list via `:include-sources`:\n\n```lisp\n(c-include \"file.h\"\n           :exclude-sources (\"/path/to/source1\"\n                             \"/path/.*source2\" ...)\n           :include-sources (\"/path/to/source1/but-include-this\"))\n```\n\nWhile everything else matching `\"/path/to/source1\"` will be excluded,\nin this example, definitions in `\"/path/to/source1/but-include-this\"`\nwill still be included (if they exist).\n\nThe next specifier, `:exclude-definitions`, excludes specific\ndefinitions by name.  These may be conflicting or unnecessary.  For\ninstance, SDL2 includes a number of functions ending in `_inline` and\nsome functions which use stdargs, all of which are unnecessary (or\nunusable).\n\nBoth of these use `cl-ppcre` regular expressions to match, thus you\nhave a great deal of flexibility with a few strings.\n\nYou may also wish to simply *rename* some symbols.  The default\nroutine generally translates symbols like you want, but you may\noccasionally find C functions named in a way that breaks this.  The\ndefault rules are as follows:\n\n* `XYZFooBar` =\u003e `XYZ-FOO-BAR`\n* `foo_barBaz` =\u003e `FOO-BAR-BAZ`\n* `_x_y` =\u003e `_X_Y` (because I think `-X-Y` looks worse)\n\nHowever if you encounter something like \"FOObar\", it is likely you\nwant \"FOO-BAR\", not \"FO-OBAR\", which is what you would get.  Thus you\ncan specify an exception:\n\n```lisp\n(c-include \"file.h\"\n           :symbol-exceptions ((\"FOObar\" . \"FOO-BAR\") ...))\n```\n\nThese are simple, case-sensitive string matches and replacements.  The\nreplacement is interned exactly, so if you specify lowercase here, you\nwill get a symbol with lowercase characters.\n\nThere is also a more complex `cl-ppcre`-based match and replace\nfacility:\n\n```lisp\n(c-include \"file.h\"\n           :symbol-regex ((\"^MATCH_string\" (PARAMS)\n                            (lambda (string matches regex) ..\n                               NEW-STRING))))\n```\n\nUsing this facility, you may specify regex-function pairs.  `PARAMS`\nspecifies further parameters to `PPCRE:CREATE-SCANNER`, e.g.,\n`:case-insensitive-mode`.  If a symbol matches the given regex, the\nfunction will be called with the string, any substring matches, and\nthe original regex (in case you want to further apply it).  You must\nreturn a string, which will then be converted by the above rules into\na final string.\n\nThis should usually be unnecessary.  The use case for its creation was\nhandling names that vary unpredictably only by *case*:\n\n```lisp\nCLUTTER_KEY_OMEGA\nCLUTTER_KEY_omega\nCLUTTER_KEY_THORN\nCLUTTER_KEY_Thorn\nCLUTTER_KEY_Adiaeresis\nCLUTTER_KEY_adiaeresis\n```\n\nIn this situation, the more complicated regex-function matching is\nnecessary.\n\nAlternatively, as was actually decided for the above clutter case,\nsince there was \"no rhyme or reason\" to the naming scheme of the\n\\#define'd constants, one may filter constant names to be interned,\nopting, instead, for referencing them through a separate constant-accessor\nmacro:\n\n```lisp\n(c-include \"file.h\"\n            :exclude-constants (\".*\")\n            :constant-accessor clutter-constant)\n;; Access constants like this:\n(clutter-constant \"CLUTTER_Z\")\n(clutter-constant \"CLUTTER_z\")\n\n```\n\n\nBy default all \"known\" architectures (at the time of writing, windows,\nmac, linux on i686 and x86_64) are generated by default.  This may not\nalways work; for instance, one architecture may require header files\nyour system lacks.  You can exclude it using the following:\n\n```lisp\n(c-include \"file.h\"\n           :exclude-arch (\"i686-pc-win32\" ...))\n```\n\nThis will exclude that target triple from being generated and causing\na warning or output if it fails.\n\nYou can also specify individual packages for symbol exports.  This can\nbe useful if, for instance, you wish to import all accessors, or all\nfunctions, or similar, while not necessarily importing everything:\n\n```lisp\n(c-include \"file.h\"\n           :definition-package PACKAGE\n           :function-package PACKAGE\n           :wrapper-package PACKAGE\n           :accessor-package PACKAGE\n           :constant-package PACKAGE\n           :extern-package PACKAGE)\n```\n\n* `:definition-package PACKAGE`: All \"definition\" symbols, which\n  include type names and function names (not to be confused with\n  function *macros* which you use in your code)\n* `:function-package PACKAGE`: All \"function\" symbols, which are all\n  macros expanding to foreign calls\n* `:wrapper-package PACKAGE`: All \"wrapper\" symbols, which are all\n  structs generated to wrap foreign record types\n* `:accessor-package PACKAGE`: All \"accessor\" symbols, which are all\n  functions generated to access record fields\n* `:constant-package PACKAGE`: All \"constant\" symbols, which are all\n  `+symbols+` representing C constants\n* `:extern-package PACKAGE`: All \"extern\" symbols, which are all\n  symbols (which are symbol-macros) representing C `extern` symbols\n\n## Wrappers and FFI\n\nAt this point you probably have definitions generated (or are\nhopefully submitting a question or bug report!).  But how to use them?\n\nWhile `cl-autowrap` uses `CFFI`, it almost exclusively uses the\nlow-level `CFFI-SYS` interface.  It does not use the high-level type\ntranslation interface, or even `cffi:defcfun`.  Pointers are still\nwhatever your Lisp provides.\n\nInstead, `cl-autowrap` defines a \"new\" higher-level interface I call\n`SFFI`, for \"simplified FFI\".  While CFFI's high-level interface is\nnice for manually defining types and functions, it proves difficult\nwhen trying to automatically generate things or exercise precise\ncontrol over various things like field layout.\n\nYou should never have to deal with SFFI directly, but all the\nfine-grained type information is available should you require access.\nThis is occasionally useful.  See below in the SFFI section for\ndetails.\n\nHowever, you cannot use CFFI constructs from another wrapper directly\nwith SFFI-defined functions, or vice versa, but you can always use\npointers between the two.\n\n### Functions\n\n`cl-autowrap` defines *macros* which wrap C calls with a few helpful\nfeatures:\n\n* Wrappers (see below) or pointers are accepted for any\n  pointer-to-struct (or union)\n* Symbols *or* integers are accepted for any `enum`\n* Lisp strings will be temporarily converted to C strings, then freed,\n  for `char*` or `unsigned char*`.  (If you need these to persist, you\n  must provide your own pointer!)\n* For `char*` and `unsigned char*` returns, both a lisp string and a\n  pointer are returned as `VALUES`, so you can free the pointer if\n  necessary.  You may prevent this conversion, and receive only the\n  pointer, if you wrap the call in `INHIBIT-STRING-CONVERSION`:\n\n```lisp\n(inhibit-string-conversion (function-returning-string ...))\n  ;; =\u003e pointer\n```\n\nOtherwise, the call will be like any C call; there is no other type\ntranslation.  In my experience, all but the most trivial C functions\nbenefit from some wrapping, so this shouldn't be a big issue.\n\nHowever, see \"Other Features\" below for some other helpful features,\nsuch as bitmasks.\n\n### Wrappers\n\nInstead of merely returning pointers, `cl-autowrap` defines *very\nthin* wrappers for non-atomic named types.  Wrappers are structs which\ncontain two things:\n\n*  A pointer, which is accessible with `AUTOWRAP:PTR`\n*  A `VALID-P` field, which is used for storing pointer validity,\n   and can be checked by `AUTOWRAP:VALID-P`\n\nWrappers are extremely useful for \"safely\" managing pointers, and are\nmeant to be safe and \"pretty\" enough for users of your wrapper to use\ndirectly.  Any dereference using `PTR` automatically checks validity,\nand you can use finalizers to clean them up.  Note however that this\nis up to you: `cl-autowrap` merely provides the facility, nothing\nelse.  See \"Garbage Collection and Wrappers\" below.\n\nAdditionally, `cl-autowrap` generates a correct \"type hierarchy\", as\nmuch as such applies to C:\n\n```c\nstruct x { ... };\ntypedef struct x y;\n```\n\nResults in:\n\n```lisp\n(defstruct (x (:include wrapper)))\n(defstruct (y (:include x)))\n```\n\nThis ensures type compatibility where the C side may arbitrarily\nspecify compatible type aliases.\n\nYou may also obtain a \"child\" wrapper for a struct which is a field in\nanother struct, using accessors:\n\n```c\nstruct foo_t {\n   :\n   struct { int a, b; } x;\n};\n```\n\n```lisp\n(let* ((foo (get-foo-somehow))\n       (x (foo-t.x foo)))\n  :\n  :\n  ... )\n```\n\nThis keeps a reference to the parent.  These may also be safely\ndereferenced using `AUTOWRAP:PTR`, and checked using\n`AUTOWRAP:VALID-P`.  Because there is a reference is kept to the\nparent, even if a reference is discarded by the user, the child is\nstill safe to use.\n\n### Garbage Collection and Wrappers\n\nOne of the primary motivators behind wrappers is the ability to easily\ngarbage collect C data.  However, this still requires some care.  To\nthis end, the `AUTOCOLLECT` macro has been added; see below.\n\nFirst, nothing besides checking is done automatically.  Pointers are\nassumed valid when they are returned and made into wrappers.  Any\nfurther invalidation and garbage collection must be handled by the one\nwriting the wrapper.\n\n**Important:** Absolutely no effort is made to keep wrappers unique or\nmanage duplicates.  Again: **YOU CAN HAVE DUPLICATE WRAPPERS AND THIS\nCAN LEAD TO BAD THINGS.**  Generally this should only occur if you\nobtain the same pointer from a C API multiple times, such as a\nfunction which returns a global context pointer.  It is up to you to\nhandle this.  *Beware.*\n\nOnce you are aware of this, you can use something like\n`trivial-garbage` to free pointers when you need:\n\n```lisp\n(defun lispy-get-thing ()\n  (let* ((thing (get-thing))\n         (ptr (autowrap:ptr thing)))\n    (tg:finalize thing (lambda () (free-thing ptr)))\n    thing))\n```\n\nNote as as always to **never** reference the object, only the pointer,\nin the finalizer, or it will never be collected.\n\nIt is often useful to free things when you still have a reference.  In\nthis case, the pointer becomes invalid, and this is also handled by\n`WRAPPER`:\n\n```lisp\n(defun lispy-free-thing (thing)\n  (unwind-protect (free-thing thing)\n    (tg:cancel-finalization thing)\n    (autowrap:invalidate thing)))\n```\n\nIn this case, further attempts to dereference `THING` via\n`AUTOWRAP:PTR` will result in an `INVALID-WRAPPER` error.\n\nYou may be tempted to do this:\n\n```lisp\n(defun bad-free-thing (thing)\n  (tg:cancel-finalization thing)\n  (autowrap:invalidate thing)\n  (free-thing thing))\n```\n\nUnfortunately, since you invalidated `THING`, when you pass it to\n`FREE-THING`, it will be invalid ... resulting in an error.\n\n**Never manage \"child\" wrapper objects.** This probably goes without\nsaying, but they're tied to the parent object, and not meant to be\nmanaged separately.\n\nAlso, you may be tempted to do this, to avoid \"dangling pointers\":\n\n```lisp\n(defun terrible-get-thing ()\n  (let* ((thing (get-thing))\n         (ptr (autowrap:ptr thing)))\n    (tg:finalize thing\n      (lambda ()\n        (free-thing ptr)\n        (setf (autowrap:wrapper-ptr thing)\n              (cffi:null-pointer))))\n    thing))\n```\n\nThis is both wrong and silly: there is a reference to `THING` in\nthe finalizer, so it will never get freed.  And if you had gotten here\nnormally, there would be *no* references, so nothing would have the\ndangling pointer!\n\nTo facilitate doing this correctly, the `AUTOCOLLECT` macro has been\nadded:\n\n```lisp\n(autocollect (\u0026optional PTR) WRAPPER-FORM \u0026body) =\u003e WRAPPER-FORM-RESULT\n```\n\nIf you are using `trivial-garbage`, this will extract the pointer from\n`WRAPPER-FORM` and call `tg:finalize` on the wrapper.  The body forms\nshould use `POINTER` to free the object.  If you are not using\n`trivial-garbage`, it will produce an error.\n\nFor instance:\n\n```lisp\n(autocollect (pointer)\n    (get-thing)\n  (free-thing pointer)) ;; =\u003e THING-WRAPPER\n```\n\nThis will call `GET-THING` and finalize the resulting wrapper with the\nbody.  `POINTER` is the pointer; this defaults to the symbol `PTR`.\n\n**This is not fool-proof.**  Things to watch out for:\n\n* If you reference the wrapper, and not the pointer, it will never be\n  collected.\n* If you try to autocollect a child wrapper, you will probably crash.\n* If you provide a function to manually free resources, *you must use*\n  `tg:cancel-finalization` or this finalizer will still be called,\n  likely double-freeing the memory and crashing.\n* It's still up to you to call something to free the pointer.\n\n### Accessors\n\nHaving wrappers and functions are nice, but getting at the data is\nimportant too.  Accessors are generated recursively (up to a depth of\n5, barring recursive types) for highly convenient access.  From the\ntop:\n\n```c\ntypedef struct foo {\n  int a, b;\n  char c[3];\n\n  struct {\n    unsigned int b0 : 2, b1 : 3;\n\n    struct {\n      char x, y;\n    } s;\n  } x[2];\n} foo_t;\n```\n\nAccessors are named starting with their type name (in this case, `FOO`\nand `FOO-T`), followed by fields, separated by dots.  There is no\nreader magic here: these are functions with dots as part of the name.\n(Dots were used mostly for disambiguation; if only dashes were used,\nname collision would be probable, since underscores are converted to\ndashes by default.)\n\nThe following special cases are available:\n\n* `type.foo` in the case of `foo` being a record type (struct or\n  union), will return a child wrapper.\n* `type.foo` in the case of `foo` being a pointer will return the\n  pointer\n* `type.foo\u0026` will return a *pointer* to the *field*, not a wrapper,\n  regardless of the type of `foo`.  If `foo` is a pointer, then you\n  get a pointer-pointer.  This is just the same as `\u0026(x.foo)` in C.\n  This does not exist for bitfields.\n* `type.foo*` will *dereference* `foo` where `foo` is a pointer to a\n  well-defined type, including record fields. E.g., `type.foo*.bar`;\n  there is no `type.foo.bar`.\n* `type.foo[]` references an *array element*, where `foo` is declared\n  as an array (not just as a pointer).  Array indices are specified\n  in order after the object: `(type.foo[].bar[] obj i0 i1)` is the\n  equivalent of C's `obj.foo[i0].bar[i1]`.\n\nAdditionally, `SETF` can set almost any field.  The exceptions are any\naccessor which dereferences a record (i.e. returns a child wrapper),\nor is suffixed with `\u0026`.\n\nBitfields are supported under the assumption that they are packed\nLSB-to-MSB on little endian and MSB-to-LSB on big endian\narchitectures.  If you *actually encounter* a problem with this, file\na bug report with full details: the architecture, OS, lisp, C\ncompiler, and an example struct.  Theoretical possibilities are not\nconsidered bugs.\n\nNote that bitfield operations cannot be done atomically and *may* not\nbe done field-atomically (that is, you *may* have to lock the entire\nstruct).  Additionally, you cannot take the address of a bitfield.\nHowever, you *can* get information from SFFI metadata, or simply using\nthe convenience function `AUTOWRAP:BITFIELD-MASK`.\n\n## Other Features\n\n`cl-autowrap` has a number of other features that have not been\ndiscussed:\n\n* Allocation\n* Enums\n* Bitmasks\n* Callbacks\n* SFFI metadata and functions\n\n### Allocation\n\nSince autowrap implements its own higher-level constructs over\nlower-level CFFI, you can't use CFFI's `FOREIGN-ALLOC` or similar\nfunctions and macros to easily allocate foreign records.  Thus there\nare new constructs for doing so:\n\n```lisp\n(let ((thing (autowrap:alloc 'type)))\n  :\n  (autowrap:free thing))\n```\n\nAs you might expect, `ALLOC` will allocate memory of sufficient size\nfor `TYPE`, and `FREE` will free it (and invalidate the wrapper for\nyou).  Note that if you are doing garbage collection as above, this\ndoes **NOT** remove finalizers for you: you MUST take care of this\nyourself where applicable.\n\nThere are also macros which will help with temporary allocation:\n\n```lisp\n(with-alloc (thing 'type)\n   :\n   :\n   )\n```\n\nThis will take care of allocation and freeing within the block.  You\nshould not use finalizers here.  If you try to reference the value\noutside of the scope of the block, it will be invalid.  If you wish to\nallocate multiple objects and free them, you can use the following:\n\n```lisp\n(with-many-alloc ((thing1 'type1)\n                  (thing2 'type2)\n                  :\n                   )\n  :\n  )\n```\n\nNote that while any `typedef` type aliases can be referenced simply by\nsymbol as in C, record types are called `(:struct (NAME))` or `(:union\n(NAME))`, and also like C, you must write this out if there is no type\nalias for `NAME`.  For example:\n\n```c\nstruct X { ... };\ntypedef struct Y { ... } Y;\n\nint main() {\n    struct X foo;    /* No type alias */\n    Y bar;           /* Type alias */\n}\n```\n\n```lisp\n(with-many-alloc ((foo '(:struct (X))) ;; No type alias\n                  (bar 'Y))            ;; Type alias\n    :\n    )\n```\n\n### Arrays\n\nIn addition to single objects, autowrap also allows allocation and\nreference to arrays of objects.  **This is less safe, however**: there\nare no provisions for bounds-checking, since the data is simply not\nthere.  (While in theory, we could add size data on the lisp side,\nthis is a false sense of security, since you will often be dealing\narrays from C.)\n\nAllocation methods all take an optional `COUNT` parameter:\n\n```lisp\n(alloc x 'type 3)\n\n(with-alloc (x 'type 5) ...)\n\n(with-many-alloc ((x 'type 5)\n                  (y 'type 2))\n  ...)\n```\n\nTo reference these, you can use `C-APTR` and `C-AREF`:\n\n```lisp\n(c-aptr x 1) ;; =\u003e raw pointer\n(c-aref y 2) ;; =\u003e wrapper\n```\n\nUnfortunately, this may present some performance issues, since\n*unlike* record accessors, the type must be looked up at runtime.  In\ntheory, autowrap could generate array accessors for all types, but\nthis would vastly increase the number of accessors generated with\nlittle value, since most will not be used.\n\nInstead, you may specify the type explicitly:\n\n```lisp\n(c-aptr x 1 'type) ;; =\u003e pointer\n(c-aptr y 2 'type) ;; =\u003e wrapper\n```\n\nIn this case, as long as `'type` is `constant-p`, the compiler macro\nshould expand it at compile-time.\n\nBasic C types (e.g., `:int`, `:char`, etc) are also supported; in this\ncase, a wrapper is not returned, but the value itself:\n\n```lisp\n(c-aref x 1 :int) ;; =\u003e number\n```\n\nYou can also set array members *for basic types only*:\n\n```lisp\n(setf (c-aref x 1 :int) 10)\n```\n\nIn both of these cases, since autowrap does not provide additional\nwrappers for basic types, you *must* specify the type explicitly.\n\n### Enums\n\nEnums are imported and created as types, but they're typically used by\nspecifying a keyword:\n\n```c\nenum E {\n  FOO_X, FOO_Y, FOO_Z\n};\n\nvoid fun(E);\n```\n\n```lisp\n(fun :x)\n```\n\nAs you can see, common prefixes are eliminated and the symbols are\ninterned as keywords.  Additionally, functions taking enum symbols can\n*also* take numbers:\n\n```lisp\n(fun 1)\n```\n\nYou can also find the value or keyword for an enum as follows:\n\n```lisp\n(autowrap:enum-key '(:enum (enum-name)) :key)\n(autowrap:enum-value '(:enum (enum-name)) 1)\n```\n\nAn actual `AUTOWRAP:FOREIGN-ENUM` can be used in place of `'enum-name`\nif desired; otherwise it will be looked up via `AUTOWRAP:FIND-TYPE`.\n\n### Bitmasks\n\nBitmasks aren't actually a type in C, and are often defined as\nconstants instead of enums or similar.  Therefore, there is no real\nautomatic way to determine a bitmask.  Thus `cl-autowrap` provides a\nnumber of convenience facilities for doing this:\n\n```lisp\n(autowrap:define-bitmask 'NAME\n  '((:key1 . #x0001)\n     :\n      ...))\n```\n\nThis defines a bitmask called `NAME`, which is separate from other C\ntypes, and can be used with the `MASK` function:\n\n```\n(some-function (autowrap:mask 'NAME :key1 :key5))\n```\n\nThis also has a compiler macro which will expand to an integer\nconstant if the value can be determined at compile-time.\n\nAdditionally, to aid in converting predefined constants to bitmasks,\nthere is the following macro, which expands to an\n`AUTOWRAP:DEFINE-BITMASK` call:\n\n```lisp\n(autowrap:define-bitmask-from-constants (name)\n  +some-foo+\n  +some-bar+\n  +some-baz+)\n```\n\nThis essentially expands to the following:\n\n```lisp\n(autowrap:define-bitmask 'name\n  (list `(:foo . ,+some-foo+)\n        `(:bar . ,+some-bar+)\n        `(:baz . ,+some-baz+)))\n```\n\n### Callbacks\n\nAutowrap now provides a thin layer on top of `CFFI-SYS:%DEFCALLBACK`:\n\n```lisp\n(autowrap:defcallback NAME RETURN-TYPE\n    ((PARAM TYPE)\n     ...)\n  ...)\n```\n\nThe main difference is that you may specify SFFI type aliases as\nparameters, since these are not available to the higher-level\n`CFFI:DEFCALLBACK`.\n\nAdditionally, there is the following:\n\n```lisp\n(autowrap:callback 'name)\n```\n\nThis simply expands to `CFFI-SYS:%CALLBACK`, but is provided for\nconvenience.\n\n### SFFI Metadata and Functions\n\nThis is not fully-documented at the moment, but full access to\nmetadata and definition functions is available.  For instance:\n\n```lisp\n(autowrap:find-type '(:struct (struct-name)))\n```\n\nThis will return the object that represents `struct struct_name`, or\nnil.  If nothing else, it should be fairly easy to inspect this value\nand look at fields, types, etc.  Accessors are exported for all types\n(or should be); see `package.lisp` for a complete list.\n\nThese values can certainly be useful when doing various tricky things\nwith C data, and it's also certainly possible to manually write\ndefinitions for every type and generate lisp functions, though for\nrecords (i.e. struct and union), this requires explicitly specifying\nbit sizes and field layouts.  While probably not directly useful (or\nnecessary) for importing C types, these could be useful for generating\nsimilar definitions via other means than `c2ffi`.\n\n## Copying\n\nThis is licensed under the [BSD\n2-Clause](http://opensource.org/licenses/BSD-2-Clause) license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frpav%2Fcl-autowrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frpav%2Fcl-autowrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frpav%2Fcl-autowrap/lists"}