From 0a3b3d6f3b2180d93d10a1c8a7159cd81b64aded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aurel=20Bi=CC=81ly=CC=81?= Date: Sun, 19 Mar 2023 23:46:09 +0100 Subject: [PATCH] manual deploy for #55 --- advanced-cycles.html | 56 +++++++ advanced.html | 23 +++ amlib.html | 43 ++++++ ammer-stages.html | 23 --- ammer-testing.html | 28 ---- ammer.html | 16 -- configuration-general.html | 24 --- configuration-library.html | 78 +++++++--- configuration-project.html | 30 ++++ configuration-providing.html | 39 +++++ configuration.html | 177 +++------------------ core-api.html | 42 +++++ core-new-platform.html | 52 +++++++ core.html | 37 +++++ css/highlight.css | 167 ++++++++++++++++++++ css/style.css | 247 +++++++++++++++++++++++++++++- definition-enum.html | 43 ------ definition-ffi-callbacks.html | 59 ------- definition-ffi-size.html | 44 ------ definition-ffi.html | 129 +--------------- definition-library-constants.html | 48 +----- definition-library-functions.html | 56 +++++-- definition-library-variables.html | 45 ++++++ definition-library.html | 49 ++++-- definition-link.html | 39 +++-- definition-metadata.html | 79 +--------- definition-sub.html | 41 ++--- definition-type-callbacks.html | 84 ++++++++++ definition-type-enum.html | 38 +++++ definition-type-haxe.html | 40 +++++ definition-type-instance.html | 39 +++++ definition-type-nested.html | 102 ------------ definition-type-opaque.html | 42 +++++ definition-type-struct.html | 102 ++++++++++++ definition-type.html | 94 +++--------- definition.html | 21 ++- index.html | 146 ++++++++++++++++-- intro-installation.html | 32 ++-- intro-overview.html | 87 +++++++++++ intro-sample.html | 19 --- intro-start.html | 47 +++--- intro-terminology.html | 44 ++++++ intro-troubleshooting.html | 17 -- intro-use.html | 151 +++++++++++++++--- library.html | 29 ---- ref-annot.html | 70 +++++++++ ref-def.html | 99 ++++++++++++ ref-ffi.html | 241 +++++++++++++++++++++++++++++ ref-flags.html | 140 +++++++++++++++++ ref-lib.html | 46 ++++++ ref.html | 31 ++++ search.js | 81 ++++++++++ search.json | 1 + target-cs.html | 40 +++++ target-eval.html | 35 ++++- target-feature-parity.html | 36 +++++ target-hashlink.html | 50 ++++-- target-hxcpp.html | 44 ++++-- target-java.html | 45 ++++++ target-lua.html | 44 ++++-- target-neko.html | 45 ++++++ target-nodejs.html | 43 ++++++ target-python.html | 47 ++++++ target.html | 92 ++++------- 64 files changed, 2936 insertions(+), 1142 deletions(-) create mode 100644 advanced-cycles.html create mode 100644 advanced.html create mode 100644 amlib.html delete mode 100644 ammer-stages.html delete mode 100644 ammer-testing.html delete mode 100644 ammer.html delete mode 100644 configuration-general.html create mode 100644 configuration-project.html create mode 100644 configuration-providing.html create mode 100644 core-api.html create mode 100644 core-new-platform.html create mode 100644 core.html create mode 100644 css/highlight.css delete mode 100644 definition-enum.html delete mode 100644 definition-ffi-callbacks.html delete mode 100644 definition-ffi-size.html create mode 100644 definition-library-variables.html create mode 100644 definition-type-callbacks.html create mode 100644 definition-type-enum.html create mode 100644 definition-type-haxe.html create mode 100644 definition-type-instance.html delete mode 100644 definition-type-nested.html create mode 100644 definition-type-opaque.html create mode 100644 definition-type-struct.html create mode 100644 intro-overview.html delete mode 100644 intro-sample.html create mode 100644 intro-terminology.html delete mode 100644 intro-troubleshooting.html delete mode 100644 library.html create mode 100644 ref-annot.html create mode 100644 ref-def.html create mode 100644 ref-ffi.html create mode 100644 ref-flags.html create mode 100644 ref-lib.html create mode 100644 ref.html create mode 100644 search.js create mode 100644 search.json create mode 100644 target-cs.html create mode 100644 target-feature-parity.html create mode 100644 target-java.html create mode 100644 target-neko.html create mode 100644 target-nodejs.html create mode 100644 target-python.html diff --git a/advanced-cycles.html b/advanced-cycles.html new file mode 100644 index 0000000..e444d1b --- /dev/null +++ b/advanced-cycles.html @@ -0,0 +1,56 @@ + + Type cycles – ammer manual + + + + + +

ammer

+ +

Type cycles

In linking subdefinitions, it is recommended to link any library to all of its subdefinitions using the @:ammer.sub metadata. Why is this necessary?

+

Consider the following types:

+
// in file Foobar.hx
+@:ammer.sub((_ : FoobarStruct))
+@:ammer.sub((_ : FoobarSub))
+class Foobar extends ammer.def.Library<"foobar"> {
+  public static function some_function():FoobarStruct;
+}
+
+// in file FoobarStruct.hx
+class FoobarStruct extends ammer.def.Struct<"foobar_t", Foobar> {
+  // ...
+}
+
+// in file FoobarSub.hx
+class FoobarSub extends ammer.def.Sublibrary<Foobar> {
+  public static function another_function():Void;
+}

Between Foobar and FoobarSub, there is a two-way link:

+ +

If the @:ammer.sub((_ : FoobarSub)) annotation was omitted, then the following client code could cause a compilation failure:

+
Foobar.some_function();
+FoobarSub.another_function();

This is because Haxe performs typing on demand: the Foobar module (in the file Foobar.hx) is not discovered and typed until the first time it is needed. This can happen if a type (and its static method) declared in that module is used, as in the first line.

+

However, Foobar is not a regular Haxe type: it is an ammer-annotated library definition. When an ammer library is typed, the following steps take place (simplified):

+ +

Without the @:ammer.sub((_ : FoobarSub)) annotation on Foobar, the first line of the client only causes the Haxe compiler to discover Foobar and FoobarStruct. When typing the second line (the call to FoobarSub.another_function), FoobarSub is discovered, but it cannot be added to Foobar anymore: the library was finalised and the glue code was already generated.

+

The safe recommendation is therefore to always use @:ammer.sub, even when other fields would cause the Haxe compiler to discover the subdefinitions.

+
+ « Previous: Advanced topics + Next: ammer-core » + + \ No newline at end of file diff --git a/advanced.html b/advanced.html new file mode 100644 index 0000000..eda6968 --- /dev/null +++ b/advanced.html @@ -0,0 +1,23 @@ + + Advanced topics – ammer manual + + + + + +

ammer

+ +

Advanced topics

+ « Previous: amlib + Next: Type cycles » + + \ No newline at end of file diff --git a/amlib.html b/amlib.html new file mode 100644 index 0000000..f42fdbb --- /dev/null +++ b/amlib.html @@ -0,0 +1,43 @@ + + amlib – ammer manual + + + + + +

ammer

+ +

amlib

TODO:

+ +
+ « Previous: List of annotations + Next: Advanced topics » + + \ No newline at end of file diff --git a/ammer-stages.html b/ammer-stages.html deleted file mode 100644 index 4ae0568..0000000 --- a/ammer-stages.html +++ /dev/null @@ -1,23 +0,0 @@ - - Compilation stages – ammer manual - - - -

ammer

- -

Compilation stages

External libraries are built in up to four separate stages:

- -
- « Previous: Testing - - - \ No newline at end of file diff --git a/ammer-testing.html b/ammer-testing.html deleted file mode 100644 index b4264f2..0000000 --- a/ammer-testing.html +++ /dev/null @@ -1,28 +0,0 @@ - - Testing – ammer manual - - - -

ammer

- -

Testing

A suite of unit tests is provided in the tests directory. There is a script provided for each OS (test-windows.bat, test-osx.sh, test-linux.sh), which:

- -
- « Previous: Implementation details - Next: Compilation stages » - - \ No newline at end of file diff --git a/ammer.html b/ammer.html deleted file mode 100644 index 4c4d436..0000000 --- a/ammer.html +++ /dev/null @@ -1,16 +0,0 @@ - - Implementation details – ammer manual - - - -

ammer

- -

Implementation details

- « Previous: Native library development - Next: Testing » - - \ No newline at end of file diff --git a/configuration-general.html b/configuration-general.html deleted file mode 100644 index 417f7b1..0000000 --- a/configuration-general.html +++ /dev/null @@ -1,24 +0,0 @@ - - General configuration – ammer manual - - - -

ammer

- -

General configuration

ammer.makefiles

Optional, default value: yes

-

When defined and the value is not no, Makefiles will be generated. Otherwise, ammer will try to emulate the behaviour of make and invoke compilers directly when changes are detected.

-

ammer.msvc

Optional, default value: yes on Windows, no on other platforms

-

When defined and the value is not no, Makefiles will be generated for use with MSVC compiler tools.

-
# don't use MSVC even on Windows
--D ammer.msvc=no
-

ammer.msvcPath

Optional, default value: ""

-

By default, nmake and cl are assumed to be in the environment's PATH and are invoked directly. When ammer.msvcPath is defined and MSVC is used, calls to nmake and cl will be prefixed with the defined path instead.

-
- « Previous: Configuration - Next: Library configuration » - - \ No newline at end of file diff --git a/configuration-library.html b/configuration-library.html index 5044bbc..fdb809c 100644 --- a/configuration-library.html +++ b/configuration-library.html @@ -2,35 +2,69 @@ Library configuration – ammer manual + +

ammer

- -

Library configuration

External libraries are declared by defining a Haxe class which extends ammer.Library<...>, with the type parameter being the identifier used for the library in the rest of the configuration.

-
class Foobar extends ammer.Library<"foobar"> { ... }
-

The identifier should only consist of letters and should be unique. Additional configuration of the library is done with compile-time defines, ideally placed in the project's hxml build file. In the following paragraph, <name> should be replaced by the library identifier.

-

ammer.lib.<name>.include

Required

-

The path to the include directory of the library, which contains the header files (.h). This path may be relative to the current working directory that haxe was invoked in.

-

ammer.lib.<name>.library

Required

-

The path to the lib directory of the library, which contains the dynamic library files (.dll, .dylib, .so). This path may be relative to the current working directory that haxe was invoked in.

-

ammer.lib.<name>.headers

Optional, default value: <name>.h

-

Comma-separated list of headers that need to be included from the library.

-
-D ammer.lib.foobar.headers=foobar.h,foobar-support.h
-

ammer.lib.<name>.abi

Optional, default value: c

-

Specify the ABI (Application Binary Interface) for the library. Supported values are:

+ +

Library configuration

Configuration flags specific to a library are typically provided by annotating the library definition with metadata, although they can be overridden on a per-project basis using defines (see providing flags).

+

Includes

The API of C libraries, consisting of function signatures and types, is typically made available by including a header file.

+
+ +

Example: including a header file

@:ammer.lib.headers.include("png.h")
+class LibPng extends ammer.def.Library<"png"> {
+  // ...
+}

In this example, the LibPng library is configured to include the png.h header file during compilation using metadata. This corresponds to the C code:

+
#include "png.h"
+ +

There are different styles of includes, see @:ammer.lib.headers.includes.

+

The @:ammer.lib.linkName metadata configures the name(s) of the dynamic library that ammer should link against such that native functions are available. This corresponds to the GCC flag -l.

+
+ +

Example: setting the link name

@:ammer.lib.linkName("png")
+class LibPng extends ammer.def.Library<"png"> {
+  // ...
+}

In this example, the LibPng library is configured to link against the png dynamic library. The C compiler will receive the argument -lpng.

+
+ +

Unless configured otherwise, an ammer library uses its identifier as the link name. Some libraries (e.g. "header-only" libraries where the implementation is enabled with a preprocessor define) have no dynamic library to link against: in this case, @:ammer.lib.linkNames([]) can be used to clear the list of link names.

+

On macOS, "frameworks" are packages of headers and dynamic libraries. The @:ammer.lib.framework metadata can be used to declare that an ammer library uses a particular framework.

+

Defines

C preprocessor defines can be enabled for a library using the @:ammer.lib.define metadata.

+

Paths

When resolving header includes and when linking, the compiler needs to know where to look. ammer libraries can be configured with include paths and library paths. These paths correspond to the GCC flags -I and -L, respectively.

+

Include paths can be configured using the @:ammer.lib.includePath metadata, library paths can be configured using the @:ammer.lib.libraryPath metadata.

+

Both include paths and library paths are set relative to the file they are declared in.

+
+ +

Example: setting the include path

@:ammer.lib.includePath("../../native")
+@:ammer.lib.headers.include("png.h")
+class LibPng extends ammer.def.Library<"png"> {
+  // ...
+}

Assuming the directory hierarchy is as follows:

+
native/
+  png.h
+haxe/
+  src/
+    LibPng.hx

The compiler will look for the png.h header file in the directory native.

+
+ +

Language

By default, ammer generates glue code in the C language. For libraries requiring the use of another language, the language can be changed using the @:ammer.lib.language metadata. Currently supported languages are:

    -
  • c - regular linkage, C libraries
  • -
  • cpp - C++ linkage
  • +
  • C - C
  • +
  • Cpp - C++
  • +
  • ObjC - Objective-C
  • +
  • ObjCpp - Objective-C++
-

ammer.lib.<name>.linkName

Optional, default value: <name>

-

The name to use when linking the library. This is the name appended to -l for GCC-based compilers.

-
-D ammer.lib.zlib.linkName=z
-# library "zlib" will be linked with "-lz"
- « Previous: General configuration + « Previous: Project-wide configuration Next: Target details » \ No newline at end of file diff --git a/configuration-project.html b/configuration-project.html new file mode 100644 index 0000000..184f59e --- /dev/null +++ b/configuration-project.html @@ -0,0 +1,30 @@ + + Project-wide configuration – ammer manual + + + + + +

ammer

+ +

Project-wide configuration

When building a project that uses an ammer library there are two flags which are required: the build and output paths. Other, optional flags, allow enabling the debug mode for ammer, setting target-specific options, or configuring the build system.

+

Paths

There are two paths that need to be configured before ammer can continue compilation.

+

The build path, configured using -D ammer.buildPath, specifies a path used as an intermediate directory. During compilation, ammer creates C files containing the glue code required to use a native library with the currently selected Haxe target. These files, as well as the intermediate outputs of the C compiler, are all placed into the build path. The build path is created if it does not exist.

+

The output path, configured using -D ammer.outputPath, specifies the path for the resulting ammer-built dynamic libraries, which are files with the extensions .dll, .so, .dylib, .hdll, or .ndll. These files must be distributed with the final executable for the library to function properly.

+

Debug mode

Full debug logging for ammer can be enabled using -D ammer.debug=all. During compilation, this will cause a lot of additional output that may be useful for ammer-debugging purposes.

+

Target-specific configuration

The configuration flags specific to each target are described in the target details section. These flags are prefixed with the target they apply to. For example, ammer.hl. is the prefix for all HashLink-specific configuration flags.

+

Build system configuration

(TODO)

+
+ « Previous: Providing flags + Next: Library configuration » + + \ No newline at end of file diff --git a/configuration-providing.html b/configuration-providing.html new file mode 100644 index 0000000..ba28326 --- /dev/null +++ b/configuration-providing.html @@ -0,0 +1,39 @@ + + Providing flags – ammer manual + + + + + +

ammer

+ +

Providing flags

A "configuration flag" in this document refers to a string key, such as ammer.buildPath associated to a value of a given type, such as String. Most configuration flags can be set using two ways:

+ +

For configuration flags associated to a particular library (for example: "which header files should be included when compiling this library"), using metadata is the more natural option. The relevant metadata are written in the same file as the definition of the library itself, which means information is not spread across too many places. Nevertheless, defines can be used to override the library behaviour on a per-project basis.

+

Configuration flags which are not associated to any library can only be provided using defines.

+
+ +

Example: providing flags

@:ammer.lib.headers.include("png.h")
+class LibPng extends ammer.def.Library<"png"> {
+  // ...
+}

In this example, the LibPng library is configured to include the png.h header file during compilation using metadata. Alternatively, the metadata can be omitted, and the flag provided using a compile-time define:

+

Note the naming convention: in the metadata case, the metadata is attached directly to the LibPng class, so providing the png identifier as part of the metadata name would be redundant. On the other hand, the compile-time define must specify which library it is referring to by using the png identifier as part of the define name.

+
+ +
+ « Previous: Configuration + Next: Project-wide configuration » + + \ No newline at end of file diff --git a/configuration.html b/configuration.html index 4a6c853..32b7c46 100644 --- a/configuration.html +++ b/configuration.html @@ -2,168 +2,29 @@ Configuration – ammer manual + +

ammer

- -

Configuration

Various defines can be specified at compile-time to configure ammer behaviour. Some of the defines below are specific to a particular target; they are ignored when compiling for a different target. Follow the links below to see longer descriptions of each define.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CategoryDefineTypeRequiredDescription
Generalammer.makefilesbooleannoEnable/disable Makefile generation
ammer.msvcbooleannoEnable/disable MSVC compilation
ammer.msvcPathstringnoPath to MSVC binaries
Libraryammer.lib.<name>.includestringyesInclude path
ammer.lib.<name>.librarystringyesLibrary path
ammer.lib.<name>.headersstring (comma-separated list)noHeaders to include
ammer.lib.<name>.abistringnoC or C++ ABI
ammer.lib.<name>.linkNamestringnoLibrary name during linking
Eval-specificammer.eval.buildstringnoEval build path
ammer.eval.outputstringnoEval output path
ammer.eval.haxeDirstringno
ammer.eval.bytecodebooleanno
HashLink-specificammer.hl.buildstringnoHashLink build path
ammer.hl.outputstringnoHashLink output path
ammer.hl.hlIncludestringnoHashLink include path
ammer.hl.hlLibrarystringnoHashLink library path
Lua-specificammer.lua.buildstringnoLua build path
ammer.lua.outputstringnoLua output path
ammer.lua.hlIncludestringnoLua include path
ammer.lua.hlLibrarystringnoLua library path
-

A boolean define is assumed to be true when set without a value as -D someDefine. Setting a boolean define to false can be achieved with -D someDefine=off, or -D someDefine=false.

+ +

Configuration

In addition to library definitions consisting of annotated Haxe classes, an ammer library must be configured such that it can be compiled properly. This section provides a guide-level explanation of the different aspects of ammer configuration, with examples. Further detail can be found in later sections.

+

Providing flags

Most configuration flags can be set using metadata or using compile-time defines.

+

Read on: Providing flags

+

Project-wide configuration

ammer requires a few flags to be set for the project as a whole before compilation can proceed.

+

Read on: Project-wide configuration

+

Library configuration

Libraries can be configured to include particular header files, to use certain paths as the include/library paths for the C compiler, to define C preprocessor values, and so forth.

+

Read on: Library configuration

- « Previous: Callbacks - Next: General configuration » + « Previous: Linking subdefinitions + Next: Providing flags » \ No newline at end of file diff --git a/core-api.html b/core-api.html new file mode 100644 index 0000000..bf1af6d --- /dev/null +++ b/core-api.html @@ -0,0 +1,42 @@ + + Interface – ammer manual + + + + + +

ammer

+ +

Interface

The main points of interaction with ammer-core are:

+ +

Platform

A Platform represents one of ammer/ammer-core targets. It can be constructed by calling ammer.core.Platform.createCurrentPlatform, or by directly calling a constructor of one of the ammer.core.plat.* types. The constructor takes a platform configuration, which is a class that contains at least the fields defined in ammer.core.plat.BaseConfig, but may contain more (required) fields: see ammer.core.plat.(Platform).(Platform)Config.

+

Platforms are used to create libraries with the createLibrary method. Once a library is finished (all its types and functions are declared), it is given to the platform with addLibrary. Finally, the finalise method returns a build program to be used by the builder.

+

Library

A Library represents a set of types and functions that will be compiled as one unit into a dynamic library (.dll, .dylib, .so).

+

As mentioned above, a Library is obtained from a platform using createLibrary: this function takes a library configuration object. This is a class that contains at least the fields defined in ammer.core.LibraryConfig, but platforms may add more fields, see ammer.core.plat.(Platform).(Platform)LibraryConfig.

+

Libraries contain a reference to a marshal object, and can have code added to them using these functions:

+
    +
  • addInclude, addCode, addHeaderCode — add code directly.
  • +
  • addFunction — adds a function with the given signature and body which can be called from Haxe using the returned expression.
  • +
  • addCallback, addStaticCallback — add functions forwarding calls to Haxe closures (or static methods, respectively) that can be called from native code using the returned name. The code provided to these functions will often make use of the closureCall and staticCall functions, which performs the actual call to a Haxe closure, given its reference.
  • +
+

Marshal

Marshal is the class that defines how values are marshalled (passed through) between Haxe and C. It has methods for each kind of type that ammer-core understands. These methods return instances of TypeMarshal, which can then be passed to functions such as addFunction to define signatures of functions.

+

Builder

A Builder represents a build system, such as GCC or MSVC, that is used to execute the build steps returned by finalising a platform, with the build function.

+
+ « Previous: ammer-core + Next: Implementing new platforms » + + \ No newline at end of file diff --git a/core-new-platform.html b/core-new-platform.html new file mode 100644 index 0000000..2d50a15 --- /dev/null +++ b/core-new-platform.html @@ -0,0 +1,52 @@ + + Implementing new platforms – ammer manual + + + + + +

ammer

+ +

Implementing new platforms

About type representation

Instances of TypeMarshal (obtained from a Marshal instance) define how any given type is to be passed between Haxe and C. This marshalling is performed in up to three steps in C code (depending on the concrete platform and type), named L1 (closest to Haxe and the concrete Haxe target), L2, and L3 (unified C representation).

+
    +
  • haxeType — the ComplexType used for this type in calls from Haxe.
  • +
  • mangled — a short representation of the type, used in identifiers and mangled function signatures.
  • +
  • l1Type, l2Type, l3Type — the C type at each step.
  • +
  • l1l2, l2l3, l3l2, l2l1 — functions which output the C code that transforms the value from one level to another. For example, l1l2 is given as first argument an expression representing the L1 representation, as second argument an identifier to which the L2 representation will be written, and returns the code that performs e.g. (l2) = transform((l1));. The generated code may span multiple lines and may require multiple method calls interacting with the current platform's FFI mechanism.
  • +
+

Implementing the platform file

To create a new Platform, it is best to follow examples of existing platforms, whose implementations are in the ammer.core.plat package. There is also a None platform which performs no-ops or raises exceptions for all of its operations; it can also serve as a good template file for new platform implementations.

+

Types such as ammer.core.Platform and ammer.core.PlatformId should also be adapted to make ammer-core aware of the new platform.

+

When developing the actual implementation, a rough guideline is as follow:

+
    +
  • Start with outputting any C glue code.
  • +
  • Implement addNamedFunction (with dummy arguments at first).
  • +
  • Implement types in Marshal, enabling tests one at a time.
      +
    • The simplest test is probably TestBools, requiring only the Bool type marshalling to work.
    • +
    +
  • +
  • Implement the finalise steps to get a dynamic library that actually compiles and links against the target's FFI mechanism.
  • +
  • Enable and pass the other tests:
      +
    • integers, TestIntegers.hx
    • +
    • floats, TestFloats.hx
    • +
    • opaques, part of TestStructs.hx
    • +
    • structs, rest of TestStructs.hx
    • +
    • bytes, TestBytes.hx
    • +
    • arrays, Haxe values, callbacks ...
    • +
    +
  • +
  • Platform configuration, polish.
  • +
+
+ « Previous: Interface + + + \ No newline at end of file diff --git a/core.html b/core.html new file mode 100644 index 0000000..2b6029a --- /dev/null +++ b/core.html @@ -0,0 +1,37 @@ + + ammer-core – ammer manual + + + + + +

ammer

+ +

ammer-core

ammer-core is a macro library that forms the foundation of ammer. Its main function is to allow each ammer target to be compiled and linked to C functions. To achieve this:

+
    +
  • For each ammer target:
      +
    • It generates code that contains the C functions, along with any glue code required by the target's FFI mechanism.
    • +
    • In each function, it marshals data from the target's native representation to its C counterparts.
    • +
    • It defines a sequence of build steps that compiles the generated glue code, including any headers and dynamic libraries required by the target's FFI mechanism.
    • +
    +
  • +
  • For each build system:
      +
    • It executes the sequence of build steps by invoking the concrete compiler/linker with appropriate arguments.
    • +
    +
  • +
+

The API of ammer-core is quite low-level and stays quite close to the C counterparts. Notably, ammer-core does not map Haxe classes and types to native libraries, it does not assume that there is a single dynamic library being defined, and it does not process metadata or defines: these are all handled by ammer.

+
+ « Previous: Type cycles + Next: Interface » + + \ No newline at end of file diff --git a/css/highlight.css b/css/highlight.css new file mode 100644 index 0000000..3074ebc --- /dev/null +++ b/css/highlight.css @@ -0,0 +1,167 @@ +// fonts +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local("Open Sans Bold"), local("OpenSans-Bold"), url("opensans-bold-ext.woff2") format("woff2"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local("Open Sans Bold"), local("OpenSans-Bold"), url("opensans-bold.woff2") format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local("Open Sans Regular"), local("OpenSans-Regular"), url("opensans-normal-ext.woff2") format("woff2"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local("Open Sans Regular"), local("OpenSans-Regular"), url("opensans-normal.woff2") format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +@font-face { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local("JetBrainsMono"), url("jetbrainsmono-regular.woff2") format("woff2"); +} +@font-face { + font-family: "JetBrainsMono"; + font-style: italic; + font-weight: 400; + font-display: swap; + src: local("JetBrainsMono"), url("jetbrainsmono-italic.woff2") format("woff2"); +} +@font-face { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 500; + font-display: swap; + src: local("JetBrainsMono"), url("jetbrainsmono-medium.woff2") format("woff2"); +} +@font-face { + font-family: "JetBrainsMono"; + font-style: italic; + font-weight: 500; + font-display: swap; + src: local("JetBrainsMono"), url("jetbrainsmono-medium-italic.woff2") format("woff2"); +} +@font-face { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local("JetBrainsMono"), url("jetbrainsmono-bold.woff2") format("woff2"); +} +@font-face { + font-family: "JetBrainsMono"; + font-style: italic; + font-weight: 700; + font-display: swap; + src: local("JetBrainsMono"), url("jetbrainsmono-bold-italic.woff2") format("woff2"); +} +@font-face { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 900; + font-display: swap; + src: local("JetBrainsMono"), url("jetbrainsmono-extrabold.woff2") format("woff2"); +} +@font-face { + font-family: "JetBrainsMono"; + font-style: italic; + font-weight: 900; + font-display: swap; + src: local("JetBrainsMono"), url("jetbrainsmono-extrabold-italic.woff2") format("woff2"); +} + +.hl { +} +.hl i { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 400; +} +.hl i.hl-kw { + color: #aa0000; +} +.hl i.hl-com { + color: #8c868f; +} +.hl i.hl-decl { + color: #3b7bb5; + font-weight: 700; +} +.hl i.hl-dummy { + display: none; +} +.hl i.hl-lit { + color: #409b1c; +} +.hl i.hl-meta { + color: #ff8000; +} +.hl i.hl-metax { + color: #ff8000; + opacity: .6; +} +.hl i.hl-op { + color: #3b7bb5; +} +.hl i.hl-stresc { + color: #409b1c; + opacity: .6; + /*color: #002bdc;*/ +} +.hl i.hl-ty { + color: #3b7bb5; +} +.hl i.hl-tyx { + color: #3b7bb5; + opacity: .6; +} +/*.hl i.hl-other { + background: #ffeeee; +}*/ + +.hl a.hll-call { + background: rgba(59, 123, 181, .14); + text-decoration: none; +} +.hl a.hll-call:hover { + background: rgba(59, 123, 181, .24); +} +.hl a.hll-def { + background: rgba(59, 123, 181, .14); + text-decoration: none; +} +.hl a.hll-def:hover { + background: rgba(59, 123, 181, .24); +} +.hl a.hll-meta { + background: rgba(255, 128, 0, .08); + text-decoration: none; +} +.hl a.hll-meta:hover { + background: rgba(255, 128, 0, .20); +} +.hl a.hll-ty { + background: rgba(59, 123, 181, .14); + text-decoration: none; +} +.hl a.hll-ty:hover { + background: rgba(59, 123, 181, .24); +} diff --git a/css/style.css b/css/style.css index 055dab7..26cc6a8 100644 --- a/css/style.css +++ b/css/style.css @@ -1 +1,246 @@ -*{box-sizing:border-box;margin:0;padding:0}html{font-size:10px}@font-face{font-family:"Open Sans";font-style:normal;font-weight:700;font-display:swap;src:local("Open Sans Bold"),local("OpenSans-Bold"),url(opensans-bold-ext.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Open Sans";font-style:normal;font-weight:700;font-display:swap;src:local("Open Sans Bold"),local("OpenSans-Bold"),url(opensans-bold.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Open Sans";font-style:normal;font-weight:400;font-display:swap;src:local("Open Sans Regular"),local("OpenSans-Regular"),url(opensans-normal-ext.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Open Sans";font-style:normal;font-weight:400;font-display:swap;src:local("Open Sans Regular"),local("OpenSans-Regular"),url(opensans-normal.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"JetBrainsMono";font-style:normal;font-weight:400;font-display:swap;src:local("JetBrainsMono"),url(jetbrainsmono-regular.woff2) format("woff2")}@font-face{font-family:"JetBrainsMono";font-style:italic;font-weight:400;font-display:swap;src:local("JetBrainsMono"),url(jetbrainsmono-italic.woff2) format("woff2")}@font-face{font-family:"JetBrainsMono";font-style:normal;font-weight:500;font-display:swap;src:local("JetBrainsMono"),url(jetbrainsmono-medium.woff2) format("woff2")}@font-face{font-family:"JetBrainsMono";font-style:italic;font-weight:500;font-display:swap;src:local("JetBrainsMono"),url(jetbrainsmono-medium-italic.woff2) format("woff2")}@font-face{font-family:"JetBrainsMono";font-style:normal;font-weight:700;font-display:swap;src:local("JetBrainsMono"),url(jetbrainsmono-bold.woff2) format("woff2")}@font-face{font-family:"JetBrainsMono";font-style:italic;font-weight:700;font-display:swap;src:local("JetBrainsMono"),url(jetbrainsmono-bold-italic.woff2) format("woff2")}@font-face{font-family:"JetBrainsMono";font-style:normal;font-weight:900;font-display:swap;src:local("JetBrainsMono"),url(jetbrainsmono-extrabold.woff2) format("woff2")}@font-face{font-family:"JetBrainsMono";font-style:italic;font-weight:900;font-display:swap;src:local("JetBrainsMono"),url(jetbrainsmono-extrabold-italic.woff2) format("woff2")}body{background:#eee;color:#444;display:grid;font-family:"Open Sans",sans-serif;font-size:1.4rem;line-height:1.9rem;grid-template-areas:"h c c" "n c c" "n l r" "f f f";grid-template-columns:300px 1fr 1fr;grid-template-rows:50px auto 50px auto}header{background:#eee;grid-area:h;position:fixed}header a{text-decoration:none}header a h1{border-bottom:2px solid #ff8000;color:#ff8000;height:50px;font-family:"JetBrainsMono";font-weight:400;padding:13px 20px 0;transition:background .1s,border .1s,color .1s;width:300px}header a h1:hover{background:#a00;border-bottom:2px solid #a00;color:#fff}#menu{background:#f8f8f8;grid-area:n;padding:20px}#menu ul{list-style:none}#menu ul ul{padding-left:15px}main{background:#fff;grid-area:c;padding:7px 20px;width:100%}#page-prev,#page-next{background:#f8f8f8;display:block;height:50px;padding:15px 20px}#page-prev:hover,#page-next:hover{background:#fff}#page-prev{grid-area:l}#page-next{grid-area:r;text-align:right}footer{background:#eee;border-top:2px solid #ddd;grid-area:f;padding:20px;text-align:right}a{color:#888;text-decoration:underline}a:hover{color:#666}main p,main h1,main h2,main h3,main ol,main ul{padding:1rem 0}main ul ul,main ol ol{padding-left:15px}main ul,main ol{list-style:inside}main pre{border:1px solid #ddd;border-radius:3px;margin:1rem 0;max-width:100%;overflow-x:auto;padding:10px}main pre code{padding-right:10px}main code{color:#666;font-family:"JetBrainsMono",monospace}main table th,main table td{padding:10px}main table th+th,main table td+td{border-left:1px solid #ddd}main table tbody tr td{border-top:1px solid #ddd}main .example{border-left:2px solid #ddd;padding:0 0 0 20px} \ No newline at end of file +* { + box-sizing: border-box; + margin: 0; + padding: 0; } + +html { + font-size: 10px; } + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local("Open Sans Bold"), local("OpenSans-Bold"), url(opensans-bold-ext.woff2) format("woff2"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local("Open Sans Bold"), local("OpenSans-Bold"), url(opensans-bold.woff2) format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local("Open Sans Regular"), local("OpenSans-Regular"), url(opensans-normal-ext.woff2) format("woff2"); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local("Open Sans Regular"), local("OpenSans-Regular"), url(opensans-normal.woff2) format("woff2"); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } +@font-face { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local("JetBrainsMono"), url(jetbrainsmono-regular.woff2) format("woff2"); } +@font-face { + font-family: "JetBrainsMono"; + font-style: italic; + font-weight: 400; + font-display: swap; + src: local("JetBrainsMono"), url(jetbrainsmono-italic.woff2) format("woff2"); } +@font-face { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 500; + font-display: swap; + src: local("JetBrainsMono"), url(jetbrainsmono-medium.woff2) format("woff2"); } +@font-face { + font-family: "JetBrainsMono"; + font-style: italic; + font-weight: 500; + font-display: swap; + src: local("JetBrainsMono"), url(jetbrainsmono-medium-italic.woff2) format("woff2"); } +@font-face { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local("JetBrainsMono"), url(jetbrainsmono-bold.woff2) format("woff2"); } +@font-face { + font-family: "JetBrainsMono"; + font-style: italic; + font-weight: 700; + font-display: swap; + src: local("JetBrainsMono"), url(jetbrainsmono-bold-italic.woff2) format("woff2"); } +@font-face { + font-family: "JetBrainsMono"; + font-style: normal; + font-weight: 900; + font-display: swap; + src: local("JetBrainsMono"), url(jetbrainsmono-extrabold.woff2) format("woff2"); } +@font-face { + font-family: "JetBrainsMono"; + font-style: italic; + font-weight: 900; + font-display: swap; + src: local("JetBrainsMono"), url(jetbrainsmono-extrabold-italic.woff2) format("woff2"); } +body { + background: #fff; + color: #444; + display: grid; + font-family: "Open Sans", sans-serif; + font-size: 1.4rem; + line-height: 1.9rem; + grid-template-areas: "h c c" "n c c" "n l r" "f f f"; + grid-template-columns: 300px 1fr 1fr; + grid-template-rows: 50px auto 50px auto; } + +header { + background: #eee; + grid-area: h; + position: fixed; + z-index: 10; } + header a { + text-decoration: none; } + header a h1 { + border-bottom: 2px solid #ff8000; + color: #ff8000; + height: 50px; + font-family: "JetBrainsMono"; + font-weight: 400; + padding: 13px 20px 0; + transition: background .1s, border .1s, color .1s; + width: 300px; } + header a h1:hover { + background: #aa0000; + border-bottom: 2px solid #aa0000; + color: #fff; } + +#menu { + background: #f8f8f8; + grid-area: n; + padding: 20px; } + #menu #search { + background: #fff; + border: 1px solid #888; + cursor: pointer; + display: block; + font-family: "Open Sans", sans-serif; + font-size: 1.4rem; + font-weight: 400; + height: 25px; + left: 233px; + margin-bottom: -25px; + padding: 2px 0 2px 20px; + opacity: 0; + position: relative; + transition: left .25s, margin .25s, opacity .25s, padding .25s, width .25s; + width: 25px; } + #menu #search:active, #menu #search:focus, #menu #search:not(:placeholder-shown) { + border: 1px solid #444; + left: 0; + margin-bottom: 10px; + opacity: 1; + padding: 2px 5px 2px 25px; + width: 258px; } + #menu label { + position: relative; + left: 233px; + top: 14px; + transition: left .25s, top .25s; } + #menu label::before { + content: ""; + border: 2px solid #888; + border-radius: 100%; + display: block; + height: 10px; + left: 4px; + pointer-events: none; + position: absolute; + top: 4px; + width: 10px; } + #menu label::after { + content: ""; + background: #888; + border-radius: 3px; + display: block; + left: 18px; + pointer-events: none; + position: absolute; + width: 2px; + height: 8px; + top: 14px; + transform: rotate(-45deg); } + #menu #search:active + label, #menu #search:focus + label, #menu #search:not(:placeholder-shown) + label { + left: 0; + top: -21px; } + #menu .menu-split { + display: none; } + #menu .menu-split.show { + display: block; } + #menu ul { + list-style: none; } + #menu ul ul { + padding-left: 15px; } + +main { + background: #fff; + grid-area: c; + margin: 0 auto; + max-width: 720px; + padding: 7px 20px; + width: 100%; } + +#page-prev, #page-next { + background: #f8f8f8; + display: block; + height: 50px; + padding: 15px 20px; } + #page-prev:hover, #page-next:hover { + background: #fff; } + +#page-prev { + grid-area: l; } + +#page-next { + grid-area: r; + text-align: right; } + +footer { + background: #eee; + border-top: 2px solid #ddd; + grid-area: f; + padding: 20px; + text-align: right; } + +a { + color: #888; + text-decoration: underline; } + a:hover { + color: #666; } + +main p, main h1, main h2, main h3, main ol, main ul { + padding: 1rem 0; } +main ul ul, main ol ol { + padding-left: 15px; } +main ul, main ol { + list-style: inside; } +main pre { + border: 1px solid #ddd; + border-radius: 3px; + margin: 1rem 0; + max-width: 100%; + overflow-x: auto; + padding: 10px; } + main pre code { + padding-right: 10px; } +main code { + color: #666; + font-family: "JetBrainsMono", monospace; } +main table th, main table td { + padding: 10px; } +main table th + th, main table td + td { + border-left: 1px solid #ddd; } +main table tbody tr td { + border-top: 1px solid #ddd; } +main .example { + border-left: 2px solid #ddd; + padding: 0 0 0 20px; } diff --git a/definition-enum.html b/definition-enum.html deleted file mode 100644 index 739ec2b..0000000 --- a/definition-enum.html +++ /dev/null @@ -1,43 +0,0 @@ - - Enumerations – ammer manual - - - -

ammer

- -

Enumerations

Enumerations are collections of integer values, each with a label. In this context they should be understood as C enums, rather than Haxe's enums, which are more complex.

-

To define an enumeration, extend ammer.IntEnum<..., ...> with a regular Haxe class. The first type parameter for ammer.IntEnum should be a string identifying the native C type name (which may or may not include enum at the beginning). The second type parameter should be the ammer library this type belongs to.

-
- -

Example: enumeration definition

class FoobarEnum extends ammer.IntEnum<"enum foobar_enum_t", Foobar> {
-  // ...
-}
-

In this example, FoobarEnum is an enumeration for the Foobar library. The first type parameter is enum foobar_enum_t, which means functions which work with this datatype would accept enum foobar_enum_t.

-
- -

Individual cases of an enumeration are defined as constants.

-
- -

Example: enumeration cases

class FoobarEnum extends ammer.IntEnum<"enum foobar_enum_t", Foobar> {
-  public static var E_FOO:FoobarEnum;
-  public static var E_BAR:FoobarEnum;
-}
-

This example could correspond to the following C definition:

-
enum foobar_enum_t {
-  E_FOO,
-  E_BAR
-};
-
- -

@:ammer.native can be used on enumeration cases, just like any other constant.

-

Multiple enumeration cases can have the same underlying value. However, if this is the case, the reverse mapping (when receiving a value from a native library) is not guaranteed to work.

-

Linking

Enumerations might need to be linked with the parent library using @:ammer.sub(...). See linking subdefinitions.

-
- « Previous: Nested data - Next: Metadata » - - \ No newline at end of file diff --git a/definition-ffi-callbacks.html b/definition-ffi-callbacks.html deleted file mode 100644 index 43e227a..0000000 --- a/definition-ffi-callbacks.html +++ /dev/null @@ -1,59 +0,0 @@ - - Callbacks – ammer manual - - - -

ammer

- -

Callbacks

Native libraries can expose functions that take another function, or a "callback" as an argument. Unlike Haxe, C does not support native closures, so the most common way to emulate passing context back to a function is via "user data", an additional void * argument that is passed next to the callback. When the native library needs to call the callback, it will pass back the user data in one of its arguments.

-

ammer supports callbacks via function pointers and user data. The user data is automatically created when a closure is sent to the native library, and automatically consumed when the closure needs to be invoked.

-

A callback declaration consists of three parts split across two arguments:

-
    -
  • The actual function argument, of type ammer.ffi.Closure with two type parameters:
      -
    • The function signature. One of the arguments of the function must be of type ammer.ffi.ClosureDataUse.
    • -
    • The GC mode, one of "none", "once", "forever". See GC mode.
    • -
    -
  • -
  • A callback data argument, of type ammer.ffi.ClosureData with a type parameter that is a string referring to the name of the function argument.
  • -
-

ClosureDataUse and ClosureData arguments are only present in the API definition. At runtime, only the function argument must be passed in, with a compatible function instance.

-
- -

Example: callback

import ammer.ffi.*;
-class Foobar extends ammer.Library<"foobar"> {
-  public static function store(func:Closure<(Int, Int, ClosureDataUse)->Float, "once">, _:ClosureData<"func">):Void;
-  public static function use():Void;
-}
-

In this example, Foobar is a library with two methods. store takes a Haxe function and stores it, and use invokes it again. The C API for the above might be:

-
void store(int (*func)(int, int, void*), void *user_data);
-void use(void);
-

To use this library in Haxe code, the ClosureData and ClosureDataUse arguments are omitted, because they are inserted automatically.

-
var counter = 0;
-Foobar.store((a, b) -> {
-  trace("counter", counter++);
-  return a / b;
-});
-
-// later:
-Foobar.use(); // counter, 0
-Foobar.use(); // counter, 1
-Foobar.use(); // counter, 2
-

Note that just like a regular Haxe closure, the closure retains a reference to its context, and with it a reference to its local copy of counter.

-
- -

GC mode

When passing Haxe closures to native libraries, a lot of care must be taken to avoid potential memory leaks and segmentation faults. In all Haxe targets, the GC (garbage collector) must be able to reach Haxe-allocated objects, otherwise it deems them safe to be collected and may free their memory. This is a problem when Haxe objects are referenced by non-Haxe code, because the GC cannot follow pointers it has not allocated. Instead, they need to be explicitly registered with the GC as "GC roots".

-

To solve this issue, ammer allows three GC modes as the second type parameter of ammer.ffi.Closure:

-
    -
  • "none" - The closure is never rooted. May work with functions that are immediately invoked, or static functions.
  • -
  • "once" - The closure is rooted once, when given to the native library, and unrooted when it is invoked. Useful for one-time callbacks.
  • -
  • "forever" - The closure is rooted once, when given to the native library, and then never unrooted. Potentially useful for long-living recurring events.
  • -
-
- « Previous: Size types - Next: Configuration » - - \ No newline at end of file diff --git a/definition-ffi-size.html b/definition-ffi-size.html deleted file mode 100644 index 70fd01c..0000000 --- a/definition-ffi-size.html +++ /dev/null @@ -1,44 +0,0 @@ - - Size types – ammer manual - - - -

ammer

- -

Size types

String

Since Haxe 4, Strings consist of Unicode codepoints. Internally, different targets represent strings differently, but in ammer library definitions, strings are always understood as valid UTF-8 sequences.

-

Although the null byte is a valid Unicode codepoint, some Haxe targets use it to terminate strings, and C libraries in general use it as an end-of-string marker. This is why a single char * argument is sufficient to pass a string to native libraries; the null byte is used to detect the end of the string. To pass UTF-8 data which includes null bytes, haxe.io.Bytes has to be used instead.

-

Bytes

haxe.io.Bytes values represent arbitrary binary data. In terms of C types, these can be thought of as a pointer (unsigned char *) and a corresponding length (size_t or int). When a native library expects arbitrary binary data, it often needs to know both of these values, passed as separate arguments. On the Haxe side, however, a single argument is sufficient. To facilitate this difference, the length argument given to the native library is marked with the type ammer.ffi.SizeOf with the name of the corresponding argument as a type parameter. In Haxe code, the marked argument is not present, as it is always based on the length of the Bytes instance.

-
class Foobar extends ammer.Library<"foobar"> {
-  public static function validate(buf:haxe.io.Bytes, len:ammer.ffi.SizeOf<"buf">):Bool;
-}
-
-class Main {
-  public static function main():Void {
-    // note the `len` argument is not given:
-    trace(Foobar.validate(haxe.io.Bytes.ofHex("CAFFE00CAFFE")));
-  }
-}
-

If the size of a Bytes object is not passed along to the library at all, the argument type should be wrapped in ammer.ffi.NoSize:

-
public static function takeBuffer(buf:ammer.ffi.NoSize<haxe.io.Bytes>):Void;
-

When a C API returns a binary buffer, one of the arguments may be a pointer to which the size of the buffer will be written. This can be expressed with the type ammer.ffi.SizeOfReturn. Once again, in Haxe code, this argument will not be present.

-
class Foobar extends ammer.Library<"foobar"> {
-  public static function makeData(len:ammer.ffi.SizeOfReturn):haxe.io.Bytes;
-}
-
-class Main {
-  public static function main():Void {
-    // note the `len` argument is not given:
-    trace(Foobar.makeData());
-  }
-}
-

When a native library returns a binary buffer that is the same size as one of the input arguments, the return type can be wrapped with ammer.ffi.SameSizeAs:

-
public static function reverseBuffer(buf:haxe.io.Bytes, len:ammer.ffi.SizeOf<"buf">):ammer.ffi.SameSizeAs<haxe.io.Bytes, "buf">;
-
- « Previous: FFI types - Next: Callbacks » - - \ No newline at end of file diff --git a/definition-ffi.html b/definition-ffi.html index 1363508..e3563ac 100644 --- a/definition-ffi.html +++ b/definition-ffi.html @@ -1,123 +1,6 @@ - - FFI types – ammer manual - - - -

ammer

- -

FFI types

Haxe employs a rich type system, but many of its features cannot be translated meaningfully into library definitions, hence only a subset of basic Haxe types are supported in ammer libraries:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CategoryHaxe typeC typeNote
Built-in typesVoidvoidOnly for return types.
BoolboolFrom <stdbool.h>.
FloatdoubleDouble-precision (64-bit) floating-point number.
Intint32-bit wide signed integer.
UIntunsigned int32-bit wide unsigned integer.
Size typesStringchar *See String.
haxe.io.Bytesunsigned char * and size_tSee Bytes.
ammer.ffi.SizeOf<arg>size_t
ammer.ffi.SameSizeAs<T, arg>
ammer.ffi.SizeOfReturnsize_t *
ammer.ffi.NoSize<T>
Library datatypessubtypes of ammer.Pointer<...><type> *See library datatypes.
ammer.ffi.This<type> *Only usable as an argument type in library datatype functions.
ammer.ffi.Nested<...><type>See nested data.
Enumerationssubtypes of ammer.IntEnum<...><type>See enumerations.
CallbacksHaxe function types wrapped in ammer.ffi.Callback<..., mode><type> (*)(<type...>)See callbacks.
-
- « Previous: Metadata - Next: Size types » - - \ No newline at end of file + + + + +Page redirection +If you are not redirected automatically, follow this link. \ No newline at end of file diff --git a/definition-library-constants.html b/definition-library-constants.html index 057513c..d320b21 100644 --- a/definition-library-constants.html +++ b/definition-library-constants.html @@ -1,42 +1,6 @@ - - Constants – ammer manual - - - -

ammer

- -

Constants

Constants can be declared in library definitions using public static final fields. Their value should correspond to values which are made available by the library without any prior initialisation. Typically, these are C preprocessor defines or C enum values, available from the library headers.

-
- -

Example: constant in library definition

class Foobar extends ammer.Library<"foobar"> {
-  @:ammer.native("HELLO_WORLD")
-  public static final helloWorld:String;
-}
-

In this example, helloWorld is a string constant for the Foobar ammer library definition. The headers of the foobar native library must ensure that HELLO_WORLD is a valid C expression, for example with #define HELLO_WORLD "hello world".

-
- -

@:ammer.native can be used to specify the C expression which will be used to determine the value of a constant. There is no restriction to what the expression can be: it may be a literal, a constant, the result of a library call, and so forth. However, all constant values are initialised at the same time, typically before Haxe main is reached, so the C expression should not be a mutable value, because it will not be updated.

-

Constants are restricted to a small subset of Haxe types:

-
    -
  • Bool
  • -
  • Float
  • -
  • Int
  • -
  • String
  • -
-

Metadata applicable to constants

-

Planned features

See related issue.

-
    -
  • variables - expression re-evaluated every time the variable is used
  • -
  • bitwise flags - same as Int constants, but type safe for bitwise-or combinations
  • -
-
- « Previous: Functions - Next: Linking subdefinitions » - - \ No newline at end of file + + + + +Page redirection +If you are not redirected automatically, follow this link. \ No newline at end of file diff --git a/definition-library-functions.html b/definition-library-functions.html index 22b59fd..f52d71a 100644 --- a/definition-library-functions.html +++ b/definition-library-functions.html @@ -2,33 +2,59 @@ Functions – ammer manual + +

ammer

- -

Functions

Functions can be declared in library definitions using public static fuction fields with no function body (similar to Haxe externs).

+ +

Functions

Functions can be declared in library definitions using public static fuction fields with no function body (similar to Haxe externs).

-

Example: function in library definition

class Foobar extends ammer.Library<"foobar"> {
-  public static function hello(a:Int, b:String):Float;
-}
-

In this example, hello is a function for the Foobar ammer library definition. The function double hello(int a, char *b) must be available from the foobar native library.

+

Example: function in library definition

class Foobar extends ammer.def.Library<"foobar"> {
+  public static function hello(a:Int, b:String):Float;
+}

In this example, hello is a function in the Foobar library. The function maps to the native function double hello(int a, char *b) (in C types).

-

All return types and argument types must be written explicitly, since Haxe type inference is not compatible with native libraries. Only a subset of Haxe types can be used, and there may be some restrictions on argument names. See FFI types.

-

Macros

The same public static function syntax can be used to declare C preprocessor macro calls, but the additional metadata @:ammer.macroCall should be applied. Macros which require unusual C syntax may cause a compilation failure.

+

All return types and argument types must be written explicitly, since Haxe type inference is not compatible with native libraries. Only a subset of Haxe types can be used. See FFI types.

+

Macros

The same public static function syntax can be used to declare C preprocessor macro calls, but the additional metadata @:ammer.macroCall should be applied. Macros which require unusual C syntax may cause a compilation failure: for arbitrary C code expressions, see the next section.

+

Customising the C code

For every method declared in an ammer definition, there is glue code generated which has the following general shape:

+
target_return_type func(args...) {
+  native_args = ... // "pre": decode arguments from target-specific representation to C
+  ... // "prereturn"
+  c_return_type _return =
+    native_call(native_args...); // "return"
+  ... // "post": encode returned value to a target-specific representation, cleanup, return
+}

A large part of the function, including its exact signature, depends on the concrete target. However, ammer ensures that the initial part of the function code gets the local variables to the same state on any platform: the local variables _arg0, ..., _argN are of the C types corresponding to the declared argument types.

+

If there is additional code that should be called before the actual native call happens, it can be inserted at the point marked "prereturn" above. This is accomplished with the @:ammer.c.prereturn metadata.

+

If the native call itself should be replaced with a different C expression, this can be accomplished with the @:ammer.c.return metadata. The substring %CODE% will be replaced in the provided code with the original call expression.

+

Pure Haxe functions

The @:ammer.haxe metadata can be used to define methods on libraries which are implemented purely in Haxe and have no native counterpart. When this metadata is attached to a method (and only then), it may have a body.

Metadata applicable to functions

Metadata can be used to inject additional C code into the wrapper code, mark functions as macro calls, or provide the native name for a function. See the full metadata descriptions for more information:

+

The following metadata can be attached to function arguments:

+
« Previous: Library definition - Next: Constants » + Next: Variables » \ No newline at end of file diff --git a/definition-library-variables.html b/definition-library-variables.html new file mode 100644 index 0000000..982b936 --- /dev/null +++ b/definition-library-variables.html @@ -0,0 +1,45 @@ + + Variables – ammer manual + + + + + +

ammer

+ +

Variables

Variables can be declared in library definitions using public static var fields.

+
+ +

Example: variable in library definition

class Foobar extends ammer.def.Library<"foobar"> {
+  public static var bar:Int;
+}

In this example, bar is an integer variable in the Foobar library.

+
+ +

As for function signatures, variable types are restricted to a subset of Haxe types. See FFI types.

+

Constants

If a value from a native library is available immediately, such as constants or macro definitions, it can be declared as a constant in the ammer definition using a public static final field.

+
+ +

Example: constant in library definition

class Foobar extends ammer.def.Library<"foobar"> {
+  @:ammer.native("HELLO_WORLD")
+  public static final helloWorld:String;
+}

In this example, helloWorld is a string constant for the Foobar ammer library definition. The headers of the foobar native library must ensure that HELLO_WORLD is a valid C expression, for example with #define HELLO_WORLD "hello world".

+
+ +

@:ammer.native can be used to specify the C expression which will be used to determine the value of a constant. There is no restriction to what the expression can be: it may be a literal, a constant, the result of a library call, and so forth. However, all constant values are initialised at the same time, typically before Haxe main is reached, so the C expression should not be a mutable value, because it will not be updated.

+

Metadata applicable to variables and constants

+
+ « Previous: Functions + Next: Sublibraries » + + \ No newline at end of file diff --git a/definition-library.html b/definition-library.html index 9a1bf8e..d7e43eb 100644 --- a/definition-library.html +++ b/definition-library.html @@ -2,31 +2,54 @@ Library definition – ammer manual + +

ammer

- -

Library definition

To define a library, extend ammer.Library<...> with a regular Haxe class. The type parameter for ammer.Library should be a string identifier for the native library. This identifier is used in the library configuration, so it should only consist of letters and underscores.

+ +

Library definition

To define a library, extend ammer.def.Library<...> with a Haxe class. The type parameter for ammer.def.Library should be a string identifier for the native library. This identifier is used in the library configuration, so it must only consist of letters and underscores.

-

Example: library definition

package foo;
+

Example: library definition

package foo;
 
-class Foobar extends ammer.Library<"foobar"> {
-  // ...
-}
-

In this example, foo.Foobar is an ammer library definition for the native library called foobar. Such a definition will require at least the ammer.lib.foobar.include and ammer.lib.foobar.library compile-time defines to build. See configuration.

+
class Foobar extends ammer.def.Library<"foobar"> { + // ... +}

In this example, foo.Foobar is an ammer library definition for the native library called foobar. A library definition typically includes metadata which configures properties such as the include path, the language of the native library, headers to use, etc. See configuration for more details.

-

The fields of a library definition consist of functions and constants.

-

Metadata applicable to library definitions

« Previous: Definition Next: Functions » \ No newline at end of file diff --git a/definition-link.html b/definition-link.html index ca8f496..3822f56 100644 --- a/definition-link.html +++ b/definition-link.html @@ -2,34 +2,39 @@ Linking subdefinitions – ammer manual + +

ammer

- -

Linking subdefinitions

In addition to libraries, ammer offers three kinds of "subdefinitions":

+ +

Linking subdefinitions

In addition to libraries, ammer offers four kinds of "subdefinitions":

-

Each forms a link to the parent in its declaration (e.g. ... extends ammer.Sublibrary<ParentLibrary> ...). However, this link may need to also be declared on the parent library using the @:ammer.sub metadata.

+

Each declaration declares a link to the parent library (e.g. ... extends ammer.Sublibrary<ParentLibrary>). However, a corresponding backlink should also be declared on the parent library, using the @:ammer.sub metadata. Although this declaration is optional (for the time being), it is recommended to avoid certain compilation errors, especially if the subdefinitions are declared in separate files. See type cycles for a technical explanation.

-

Example: linking a sublibrary

// in file Foobar.hx
-@:ammer.sub((_ : FoobarSub))
-class Foobar extends ammer.Library<"foobar"> {}
+

Example: linking a sublibrary

// in file Foobar.hx
+@:ammer.sub((_ : FoobarSub))
+class Foobar extends ammer.def.Library<"foobar"> {}
 
-// in file FoobarSub.hx
-class FoobarSub extends ammer.Sublibrary<Foobar> {}
-

In this example, the Foobar library "discovers" the FoobarSub sublibrary because of the @:ammer.sub metadata. The FoobarSub sublibrary "discovers" its parent library because it is the type parameter to ammer.Sublibrary.

+
// in file FoobarSub.hx +class FoobarSub extends ammer.def.Sublibrary<Foobar> {}

In this example, Foobar links to its sublibrary using the @:ammer.sub metadata. FoobarSub links to its parent library using the type parameter of ammer.def.Sublibrary.

- -

In most cases, @:ammer.sub is not required. Subdefinitions belonging to the library are also discovered by following the types used in the library functions and variables. However, there may be cases when a subdefinition is not referred to in the parent library code. If the subdefinition is also in a separate module (file), and the compiler happens to type the parent library first, compilation will fail. As such, it is recommended to always declare subdefinitions using @:ammer.sub.

- « Previous: Constants - Next: Sublibraries » + « Previous: Callbacks + Next: Configuration » \ No newline at end of file diff --git a/definition-metadata.html b/definition-metadata.html index d380bc4..7d7952c 100644 --- a/definition-metadata.html +++ b/definition-metadata.html @@ -1,73 +1,6 @@ - - Metadata – ammer manual - - - -

ammer

- -

Metadata

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MetadataApplicable to
@:ammer.c.prereturnFunctions
@:ammer.c.returnFunctions
@:ammer.macroCallFunctions
@:ammer.nativeFunctions, constants, library datatypes
@:ammer.nativePrefixLibraries, sublibraries, library datatypes, enumerations
@:ammer.structLibrary datatypes
@:ammer.subLibraries
-

@:ammer.c.prereturn(code:String)

Applied to a function declaration to inject C code directly before the native function call.

-

@:ammer.c.return(code:String)

Applied to a function declaration to inject C code that replaces the native function call. The code string may contain the %CALL%, which will expand to the full native call.

-

Can be useful to dereference the value returned from the native library:

-
// native library has: float *version(void);
-@:ammer.c.return("*(%CALL%)") public static function version():Float;
-

@:ammer.macroCall

Applied to a function declaration to specify that is is a macro call, not a real function. This currently only makes a difference for the C++ target.

-
@:ammer.macroCall @:ammer.native("foo") public static function foo(a:Int):Int;
-

@:ammer.native(name:String)

Applied to a function declaration to specify that it has a different name in the native library than the one declared in Haxe.

-
@:ammer.native("foo_bar") public static function fooBar():Void;
-

Can be useful to avoid Haxe-reserved keywords or to preserve Haxe-like function naming conventions. Additionally allows C++ template instances to be used - multiple functions with different type signatures and names but same @:ammer.native metadata can be specified:

-
@:ammer.native("foo") public static function fooInt(arg:Int):Int;
-@:ammer.native("foo") public static function fooFloat(arg:Float):Float;
-

@:ammer.nativePrefix(prefix:String)

Applied on a library or library datatype to specify that the native names of its functions consist of prefix + function name.

-
@:ammer.nativePrefix("foo_")
-class Foobar extends ammer.Library<"foobar"> {
-  // this function will use foo_bar in the C APIs:
-  public static function bar():Void;
-}
-

@:ammer.native on a field overrides @:ammer.nativePrefix on its containing class.

-

@:ammer.struct

Applied on a library datatype to indicate that the pointer is a pointer to a struct with a known size at compile time. Adds the static method alloc and the instance method free. See struct types.

-

@:ammer.sub((_ : <Type>))

Applied on a library to indicate additional subdefinitions. The parameter must be in the form (_ : SomeType). Due to Haxe's syntax for ECheckType, the parentheses are not optional, i.e. @:ammer.sub(_ : SomeType) is not valid, but @:ammer.sub((_ : SomeType)) is. See linking subdefinitions.

-
- « Previous: Enumerations - Next: FFI types » - - \ No newline at end of file + + + + +Page redirection +If you are not redirected automatically, follow this link. \ No newline at end of file diff --git a/definition-sub.html b/definition-sub.html index 86d0805..4b6403c 100644 --- a/definition-sub.html +++ b/definition-sub.html @@ -2,35 +2,40 @@ Sublibraries – ammer manual + +

ammer

- -

Sublibraries

For better code organisation, it is possible to split a library definition into multiple classes. If the separate class still consists of static functions and not "instance" methods (in which case a library datatype is more appropriate), it can be defined as a sublibrary.

-

To define a sublibrary, extend ammer.Sublibrary<...> with a regular Haxe class. The type parameter for ammer.Sublibrary should be the ammer library this class belongs to.

+ +

Sublibraries

For better code organisation, it is possible to split a library definition into multiple classes. If the separate class consists of static functions and not "instance" methods (in which case a library datatype definition might be more appropriate), it can be defined as a sublibrary.

+

To define a sublibrary, extend ammer.def.Sublibrary<...> with a Haxe class. The type parameter for ammer.def.Sublibrary should be the ammer library this class belongs to.

-

Example: sublibrary definition

package foo;
+

Example: sublibrary definition

@:ammer.sub((_ : FoobarSub))
+class Foobar extends ammer.def.Library<"foobar"> {}
 
-@:ammer.sub((_ : FoobarSub))
-class Foobar extends ammer.Library<"foobar"> {}
-
-class FoobarSub extends ammer.Sublibrary<Foobar> {
-  // ...
-}
-

In this example, FoobarSub is a sublibrary belonging to Foobar.

+
class FoobarSub extends ammer.def.Sublibrary<Foobar> { + // ... +}

In this example, FoobarSub is a sublibrary belonging to Foobar.

-

Apart from forming a separate Haxe class, sublibraries are behave identically to libraries.

-

Linking

Sublibraries might need to be linked with the parent library using @:ammer.sub(...). See linking subdefinitions.

+

Apart from forming a separate Haxe class, sublibraries behave identically to libraries.

+

Linking

Sublibraries should be linked with the parent library using the @:ammer.sub(...) metadata to avoid compilation errors. See linking subdefinitions.

Metadata applicable to sublibraries

- « Previous: Linking subdefinitions - Next: Library datatype definition » + « Previous: Variables + Next: Datatypes » \ No newline at end of file diff --git a/definition-type-callbacks.html b/definition-type-callbacks.html new file mode 100644 index 0000000..283442e --- /dev/null +++ b/definition-type-callbacks.html @@ -0,0 +1,84 @@ + + Callbacks – ammer manual + + + + + +

ammer

+ +

Callbacks

Callbacks allow native libraries to call Haxe code, for example, to invoke a handler when an event happens. Callbacks in C generally belong to two categories:

+
    +
  • Static callbacks — the native library stores a function pointer directly.
  • +
  • Callbacks with context — the native library stores a function pointer, as well as an additional void* value which is passed back to the function.
  • +
+

In ammer, a callback is declared using the ammer.ffi.Callback<...> type, which has 5 type parameters:

+
ammer.ffi.Callback<
+  CallbackType,
+  FunctionType,
+  CallTarget,
+  CallArgs,
+  Lib
+>

The type parameters should be filled in as follows:

+
    +
  • CallbackType — The function type as seen by the native library.
  • +
  • FunctionType — The function type as seen by Haxe.
  • +
  • CallTarget — An expression (wrapped in square brackets) to reach the void* value representing the callback context, or "global".
  • +
  • CallArgs — An array of expressions representing the arguments to pass to the Haxe function.
  • +
  • Lib — The parent ammer library.
  • +
+

It may be convenient to typedef callback types when referring to them within ammer definitions.

+
+ +

Example: declaring and using a callback type

Assuming a C library with the following implementation:

+
// Type alias for the function type.
+// It receives two integer arguments, in addition to the user-defined context.
+int32_t (* callback_type)(int32_t, int32_t, void*);
+
+static callback_type *stored_fptr = NULL;
+static void *stored_context = NULL;
+
+void store_callback(callback_type *fptr, void *call_context) {
+  stored_fptr = fptr;
+  stored_context = call_context;
+}
+
+int32_t invoke_callback(int32_t a, int32_t b) {
+  return stored(a, b, stored_context);
+}

The callback type can be reflected in ammer as follows:

+
typedef CallbackType = ammer.ffi.Callback<
+  (ammer.ffi.Int32, ammer.ffi.Int32, Haxe<(Int, Int)->Int>)->ammer.ffi.Int32,
+  (Int, Int)->Int,
+  [arg2],
+  [arg0, arg1],
+  Foobar
+>;

Note that [arg2] refers to the third, void*-typed argument of callback_type, whereas [arg0, arg1] refer to the first two, int-typed arguments.

+

The ammer definition for the C library above may look like this:

+
class Foobar extends ammer.def.Library<"foobar"> {
+  public static function store_callback(_:CallbackType, _:ammer.ffi.Haxe<(Int, Int)->Int>):Void;
+  public static function invoke_callback(_:ammer.ffi.Int32, _:ammer.ffi.Int32):ammer.ffi.Int32;
+}

Finally, an example of using the library to invoke the callback:

+
var func = (a:Int, b:Int) -> { return a + b; };
+var funcRef = ammer.Lib.createHaxeRef(func);
+funcRef.incref();
+Foobar.store_callback(funcRef);
+
+// ...
+
+trace(Foobar.invoke_callback(1, 2)); // 3

Note the use of createHaxeRef: func is an instance of a Haxe type, thus it must be wrapped with a reference counter as explained in the Haxe types section.

+
+ +
+ « Previous: Haxe types + Next: Linking subdefinitions » + + \ No newline at end of file diff --git a/definition-type-enum.html b/definition-type-enum.html new file mode 100644 index 0000000..707df03 --- /dev/null +++ b/definition-type-enum.html @@ -0,0 +1,38 @@ + + Enums – ammer manual + + + + + +

ammer

+ +

Enums

Enums are sets of distinct, named values of the same type. In C, this may be an actual enum declaration, or even a set of defines. Importantly, the values of an enum should be known at compile time.

+

To define an enum type, add @:build(ammer.def.Enum.build(..., ..., ...)) to a Haxe enum abstract. The first argument parameter for ammer.def.Enum.build should be a string identifying the native C type name. The second argument should be an FFI type. The third argument should be the ammer library this type belongs to.

+

Enums should only contain variable declarations, one for each enum variant.

+
+ +

Example: enum definition

@:build(ammer.def.Enum.build("int", Int32, Foobar))
+enum abstract FoobarEnum(Int) from Int to Int {
+  @:ammer.native("FOOBAR_VAL1") var Val1;
+  @:ammer.native("FOOBAR_VAL2") var Val2;
+  // ...
+}

In this example, FoobarEnum is an enum in the Foobar library. The C type underlying this enum is a regular int. There are two variants: Val1 and Val2, which have the integer values available in the constants FOOBAR_VAL1 and FOOBAR_VAL2 at compile time.

+
+ +

Compilation

In order for Haxe to be able to use ammer enums like regular enum abstracts, the value of each variant must be known at compile time. ammer will automatically extract the appropriate values by invoking the C compiler.

+

Linking

Enums should be linked with the parent library using the @:ammer.sub(...) metadata to avoid compilation errors. See linking subdefinitions.

+
+ « Previous: Instance methods + Next: Haxe types » + + \ No newline at end of file diff --git a/definition-type-haxe.html b/definition-type-haxe.html new file mode 100644 index 0000000..b835668 --- /dev/null +++ b/definition-type-haxe.html @@ -0,0 +1,40 @@ + + Haxe types – ammer manual + + + + + +

ammer

+ +

Haxe types

C libraries often contain struct fields or function arguments of type void*, such that client code using the library can provide a pointer to its own datatypes. In ammer, such void* values can stand for instances of a Haxe type, such as a Haxe class instance.

+

Garbage collection

All Haxe targets are garbage collected, which means it is the runtime's responsibility to understand which instances are no longer needed and can be re-used to free memory. For Haxe programs which do not interact with native libraries, this is not a problem. However, as soon as a Haxe instance is passed to a native library, a problem may arise: the Haxe runtime could decide that the Haxe instance is no longer usable, so it could be freed, but a reference to it may still be obtainable via the native library.

+

The solution used in ammer is to wrap Haxe instances with a reference counter, such that the programmer can indicate when a Haxe instance is or is not in use. To pass Haxe types to native libraries, use the ammer.ffi.Haxe<...> type in ammer definitions. When calling such functions, instances of Haxe types must first be wrapped using the ammer.Lib.createHaxeRef function. The resulting value has a value field to obtain the underlying Haxe instance, as well as an incref and decref function to increment or decrement the reference counter respectively.

+

The initial reference count of a Haxe reference is 0.

+
+ +

Example: function accepting a Haxe type

class MyHaxeType { /*...*/ }
+
+class Foobar extends ammer.def.Library<"foobar"> {
+  public static function hello(a:ammer.ffi.Haxe<MyHaxeType>):Void;
+}

In this example, MyHaxeType is a regular Haxe class. The hello function of the Foobar library accepts an instance of MyHaxeType.

+
var x:MyHaxeType = #dummy expr/*...*/;
+var xr = ammer.Lib.createHaxeRef(xr);
+xr.incref();
+Foobar.hello(xr);
+xr.decref();
+ +
+ « Previous: Enums + Next: Callbacks » + + \ No newline at end of file diff --git a/definition-type-instance.html b/definition-type-instance.html new file mode 100644 index 0000000..40a51d7 --- /dev/null +++ b/definition-type-instance.html @@ -0,0 +1,39 @@ + + Instance methods – ammer manual + + + + + +

ammer

+ +

Instance methods

Although C does not have the concept of instance methods (unlike, for example, Java or C++), native libraries often define APIs which simulate such a feature by passing a pointer to a struct or opaque type as the first argument.

+

In ammer, it is possible to use such methods as instance methods rather than static methods, resulting in more readable client code. To achieve this, a function must be declared in an opaque type definition or a struct definition with two requirements:

+
    +
  • It must be declared as a function (and not a static function); and
  • +
  • one of its arguments must be of the special ammer.ffi.This type.
  • +
+

When calling instance methods declared this way, the This argument is omitted, as it is automatically filled in.

+
+ +

Example: instance method

class FoobarStruct extends ammer.def.Struct<"struct foobar_s", Foobar> {
+  public function do_something(_:ammer.ffi.This, a:Int):Int;
+}

In this example, do_something is an instance method. In Haxe code, it could be used like this:

+
var x:FoobarStruct = #dummy expr/*...*/;
+x.do_something(42);

Note that the first argument for do_something is not specified – x is used automatically.

+
+ +
+ « Previous: Structs + Next: Enums » + + \ No newline at end of file diff --git a/definition-type-nested.html b/definition-type-nested.html deleted file mode 100644 index 3c62d94..0000000 --- a/definition-type-nested.html +++ /dev/null @@ -1,102 +0,0 @@ - - Nested data – ammer manual - - - -

ammer

- -

Nested data

Instances of library datatypes in ammer refer to pointers to the actual data, which is allocated on the heap. This is true even if the instance is contained in a field that is already a part of a struct.

-
- -

Example: struct referring to struct by pointer

class FoobarA extends ammer.Pointer<"foobar_a_t", Foobar> {
-  public var val:Int;
-}
-
-class FoobarB extends ammer.Pointer<"foobar_b_t", Foobar> {
-  public var bar:FoobarA;
-}
-

In this example, FoobarA and FoobarB are library datatype for the Foobar library. FoobarB has a field bar, which refers by pointer to an instance of FoobarA. The example might correspond to the following C structs:

-
typedef struct {
-  int val;
-} foobar_a_t;
-
-typedef struct {
-  foobar_a_t *bar;
-} foobar_b_t;
-

Note the * on bar.

-
- -

If a field is instead meant to represent the struct itself, rather than a pointer to it, ammer.ffi.Nested<...> can be used.

-
- -

Example: struct referring to struct by value

class FoobarA extends ammer.Pointer<"foobar_a_t", Foobar> {
-  public var val:Int;
-}
-
-class FoobarB extends ammer.Pointer<"foobar_b_t", Foobar> {
-  public var bar:ammer.ffi.Nested<FoobarA>;
-}
-

In this example, FoobarB contains an instance of FoobarA. The example might correspond to the following C structs:

-
typedef struct {
-  int val;
-} foobar_a_t;
-
-typedef struct {
-  foobar_a_t bar;
-} foobar_b_t;
-

Note that foobar_a_t is embedded directly into foobar_b_t.

-
- -

ammer.ffi.Nested<...> can also be used to model the fields of a union (and C-like ADTs).

-
- -

Example: unions and ADTs

class FoobarParent extends ammer.Pointer<"foobar_parent_t", Foobar> {
-  public var isTypeA:Bool;
-  public var aData:ammer.ffi.Nested<FoobarA>;
-  public var bData:ammer.ffi.Nested<FoobarB>;
-}
-
-class FoobarA extends ammer.Pointer<"foobar_a_t", Foobar> {
-  public var x:Int;
-  public var y:Int;
-}
-
-class FoobarB extends ammer.Pointer<"foobar_b_t", Foobar> {
-  public var f:Float;
-}
-

In this example, FoobarParent "contains" both data for a FoobarA instance and a FoobarB instance. Assuming a C definition as shown below, this could form a simple ADT.

-
typedef struct {
-  int x;
-  int y;
-} foobar_a_t;
-
-typedef struct {
-  double f;
-} foobar_b_t;
-
-typedef struct {
-  bool isTypeA;
-  union {
-    foobar_a_t aData;
-    foobar_b_t bData;
-  };
-}
-

In Haxe, one could use the ADT with a switch like so:

-
var x:FoobarParent = ...;
-switch [x.isTypeA, x] {
-  case [true, _.aData => data]:
-    trace("FoobarA", data.x, data.y);
-  case [false, _.bData => data]:
-    trace("FoobarB", data.f);
-}
-
- -
- « Previous: Library datatype definition - Next: Enumerations » - - \ No newline at end of file diff --git a/definition-type-opaque.html b/definition-type-opaque.html new file mode 100644 index 0000000..0d20422 --- /dev/null +++ b/definition-type-opaque.html @@ -0,0 +1,42 @@ + + Opaque types – ammer manual + + + + + +

ammer

+ +

Opaque types

When a native library uses a type in its API without revealing the actual fields and layout of that type (as is the case with structs), the type can be called opaque. Such values cannot be allocated or freed, and can only be used meaningfully by passing them to the methods of the native library that defined them in the first place.

+

To define an opaque type, extend ammer.def.Opaque<...> with a Haxe class. The first type parameter for ammer.def.Opaque should be a string identifying the native C type name. The second type parameter should be the ammer library this type belongs to.

+

Although opaque type definitions cannot contain any variable fields, they may still contain instance methods.

+
+ +

Example: opaque type definition

class FoobarOpaque extends ammer.def.Opaque<"opaque_t", Foobar> {
+  // ...
+}

In this example, FoobarOpaque is an opaque type of the Foobar library. The C name for this type is opaque_t.

+
+ +

Linking

Opaque types should be linked with the parent library using the @:ammer.sub(...) metadata to avoid compilation errors. See linking subdefinitions.

+

Metadata applicable to opaque types

+
+ +

Not yet implemented: large opaque types

Currently, ammer assumes every opaque type is pointer-sized or smaller. This allows passing it between Haxe and native code without any allocations. Supporting opaque types that do not fit into a pointer is a planned feature.

+
+ +
+ « Previous: Datatypes + Next: Structs » + + \ No newline at end of file diff --git a/definition-type-struct.html b/definition-type-struct.html new file mode 100644 index 0000000..e0ece45 --- /dev/null +++ b/definition-type-struct.html @@ -0,0 +1,102 @@ + + Structs – ammer manual + + + + + +

ammer

+ +

Structs

When a struct type is not opaque, its fields are known and can be read and written directly, without using a library method.

+

To define a struct type, extend ammer.def.Struct<..., ...> with a Haxe class. The first type parameter for ammer.def.Struct should be a string identifying the native C type name. The second type parameter should be the ammer library this type belongs to.

+

Struct definitions can contain variable fields, as well as instance methods.

+
+ +

Example: library datatype definition

class FoobarStruct extends ammer.def.Struct<"struct foobar_s", Foobar> {
+  // ...
+}

In this example, FoobarStruct is a struct in the Foobar library. The C name for this struct is struct foobar_s. Values of FoobarStruct in Haxe represent instances of struct foobar_s* (a pointer to struct foobar_s).

+
+ +

Instances are pointers

Note that on the Haxe side, any struct value will be represented as a pointer to a struct. This is because most ammer targets do not support arbitrarily large stack-allocated data. See passing structs directly for declaring APIs which do not use a pointer indirection.

+

Variables

Structs definitions can contain variables, declared as public var or var fields.

+
+ +

Example: struct variables

class FoobarStruct extends ammer.def.Struct<"struct foobar_s", Foobar> {
+  public var bar:Int;
+}

In this example FoobarStruct has a bar variable that can be read or written:

+
var x:FoobarStruct = #dummy expr/*...*/;
+x.bar = 3;
+var y = x.bar;
+ +

Variables map to pointer accesses in C code, so a bar variable is read as (someStruct)->bar and written as (someStruct)->bar = value. Note that any read or write variable access may have a runtime cost of a function call.

+

Allocation and deallocation

To make it possible to allocate and deallocate a struct, it must be marked with the @:ammer.alloc metadata. When annotated, several functions are made available:

+
    +
  • alloc — a static function which allocates an instance of the given struct type. Initial values for its fields can optionally be passed using an object syntax.
  • +
  • free — an instance method which deallocates the underlying allocation.
  • +
  • nullPtr — a static function which returns a null pointer of the given struct type.
  • +
+

The name of the generated functions can be changed to avoid conflicts with other functions. @:ammer.alloc is simply a convenience shortcut to the combination @:ammer.gen.alloc("alloc"), @:ammer.gen.free("free"), @:ammer.gen.nullPtr("nullPtr"), where the string arguments specify the name of each generated method.

+
+ +

Example: allocating and deallocating a struct

Given a struct definition annotated with @:ammer.alloc:

+
@:ammer.alloc
+class FoobarStruct extends ammer.def.Struct<"struct foobar_s", Foobar> {
+  public var some_field:Int;
+}

It can be allocated by calling alloc:

+
// with fields zeroed out:
+var x = FoobarStruct.alloc();
+// or with some initial values:
+var x = FoobarStruct.alloc({
+  some_field: 42,
+});

It can then be deallocated:

+
x.free();

And a null pointer can be obtained:

+
var x = FoobarStruct.nullPtr();
+ +

Passing structs directly

Native methods which take a struct directly, as opposed to a pointer to a struct, can be declared by using the special ammer.ffi.Deref<...> type. This dereferences the struct pointer just before the native method call.

+
+ +

Example: using ammer.ffi.Deref

class Foobar {
+  public static function take_struct_ptr(x:FoobarStruct):Void;
+  public static function take_struct_val(x:ammer.ffi.Deref<FoobarStruct>):Void;
+}

This example demonstrates passing a struct using a pointer and passing it directly. The corresponding C signatures could look like this:

+
void take_struct_ptr(struct foobar_s* x) { /*...*/ }
+void take_struct_val(struct foobar_s x) { /*...*/ }

Note that on the Haxe call side, the two methods are called the same way: by passing an instance of the FoobarStruct type. The dereferencing, if any, happens transparently.

+
var x:FoobarStruct = #dummy expr/*...*/;
+Foobar.take_struct_ptr(x);
+Foobar.take_struct_val(x);
+ +

A similar situation arises when a native library method returns a struct value. To obtain a pointer to the struct, a heap allocation must take place to store that struct. In ammer, return types can be wrapped with the special ammer.ffi.Alloc<...> type to achieve this.

+
+ +

Example: using ammer.ffi.Alloc

class Foobar {
+  public static function give_struct_ptr():FoobarStruct;
+  public static function give_struct_val():ammer.ffi.Alloc<FoobarStruct>;
+}

This example demonstrates a native method returning a pointer to a struct and one returning a struct directly. The corresponding C signatures could look like this:

+
struct foobar_s* give_struct_ptr() { /*...*/ }
+struct foobar_s give_struct_val() { /*...*/ }

Note that on the Haxe call side, the two methods have the same return type: an instance of FoobarStruct. The allocation, if any, happens transparently.

+
var x:FoobarStruct = Foobar.give_struct_ptr();
+var y:FoobarStruct = Foobar.give_struct_val();
+ +

Linking

Structs should be linked with the parent library using the @:ammer.sub(...) metadata to avoid compilation errors. See linking subdefinitions.

+

Metadata applicable to structs

+
+ « Previous: Opaque types + Next: Instance methods » + + \ No newline at end of file diff --git a/definition-type.html b/definition-type.html index dea669d..d36e545 100644 --- a/definition-type.html +++ b/definition-type.html @@ -1,82 +1,34 @@ - Library datatype definition – ammer manual + Datatypes – ammer manual + +

ammer

- -

Library datatype definition

To define a library datatype, extend ammer.Pointer<..., ...> with a regular Haxe class. The first type parameter for ammer.Pointer should be a string identifying the native C type name (without the *). The second type parameter should be the ammer library this type belongs to.

-
- -

Example: library datatype definition

class FoobarType extends ammer.Pointer<"foobar_t", Foobar> {
-  // ...
-}
-

In this example, FoobarType is a library datatype for the Foobar library. The first type parameter is foobar_t, which means functions which work with this datatype would accept foobar_t *.

-
- -

Sometimes it is useful to associate some functions of a library with the datatype rather than the library itself, then in Haxe code use them as non-static instance methods rather than static methods. Library datatype functions are defined just like library functions, with two differences:

-
    -
  • they are declared as public function
  • -
  • one of their arguments must be of the special ammer.ffi.This type
  • -
-

When calling instance functions of a library datatype, the This argument is omitted, as it is automatically filled in with the used instance.

-
- -

Example: library datatype function

class FoobarType extends ammer.Pointer<"foobar_t", Foobar> {
-  public function doFoobarAction(_:ammer.ffi.This, a:Int, b:Int):Int;
-}
-

In this example, doFoobarAction is a datatype function. In Haxe code, it could be used like this:

-
var x:FoobarType = ...;
-x.doFoobarAction(3, 4);
-

Note that the first argument for doFoobarAction is not specified – x is used automatically.

-
- -

The rules for identifying the native function names are the same as for library functions. Unlike libraries, library datatypes cannot contain static functions or constants.

-

Variables

Library datatypes can also have variables. Variables must be declared using public var fields.

-
- -

Example: library datatype variables

class FoobarType extends ammer.Pointer<"foobar_t", Foobar> {
-  public var bar:Int;
-}
-

In this example, FoobarType is a library datatype for the Foobar library. It has a bar variable that can be read or written:

-
var x:FoobarType = ...;
-x.bar = 3;
-var y = x.bar;
-
- -

Variables map to pointer accesses in C code, so a bar variable is read as (someStruct)->bar and written as (someStruct)->bar = value. Note that any read or write variable access has a runtime cost of a function call.

-

The rules for identifying the native variable names are the same as for functions.

-

Struct types

@:ammer.struct can be used to specify that the pointer is a pointer to a struct known at compile time (not an incomplete or extern struct). Doing this adds the static method alloc and the instance method free to the type.

-
- -

Example: library datatype struct

@:ammer.struct
-class FoobarType extends ammer.Pointer<"foobar_t", Foobar> {
-  public var bar:Int;
-}
-

In this example, FoobarType is a library datatype for the Foobar library. It is declared a struct, which means that the alloc and free methods are implicitly added. Supposing there is a Foobar.takeStruct(x:FoobarType) method:

-
var x = FoobarType.alloc();
-x.bar = 42;
-Foobar.takeStruct(x);
-x.free();
-
- -

Note that incorrect use of alloc and free may lead to memory leaks or segmentation faults at runtime. A struct that is alloc'ed once must be free'd manually at a later point, because the garbage collector cannot do it automatically. Once a struct is free'd, its fields should not be accessed, nor should the Haxe object referencing the struct be passed into any library functions, because the pointer becomes invalid.

-

Linking

Library datatypes might need to be linked with the parent library using @:ammer.sub(...). See linking subdefinitions.

-

Metadata applicable to library datatypes

-

Planned features

See related issue.

-
    -
  • Pass-by-value semantics.
  • -
  • Optimised variable access without a function call.
  • -
+ +

Datatypes

Libraries often group data into complex types such as structs. To make use of these in Haxe code and in ammer library definitions, they can be defined as Haxe types.

+

Opaque types

Opaque types are types whose fields and layout are only known to the library that defines them. Any interaction with such types happens through methods defined by the library.

+

Read on: Opaque types

+

Structs

Structs are types which contain fields, which can be read from or written to.

+

Read on: Structs

+

Enums

Enums are sets of named values of the same type.

+

Read on: Enums

+

Haxe types

Native libraries can store pointers to instances of Haxe types.

+

Read on: Haxe types

+

Callbacks

Callbacks allow Haxe code to be called by the native library.

+

Read on: Callbacks

« Previous: Sublibraries - Next: Nested data » + Next: Opaque types » \ No newline at end of file diff --git a/definition.html b/definition.html index 704e76a..5a1d254 100644 --- a/definition.html +++ b/definition.html @@ -2,20 +2,27 @@ Definition – ammer manual + +

ammer

- -

Definition

An ammer library is a set of library and library datatype definitions. Since Haxe organises code into modules and classes, both libraries and library datatypes are defined using Haxe classes.

+ +

Definition

An ammer library is a set of library definitions and library datatype definitions. Since Haxe organises code into modules and classes, both libraries and library datatypes are defined using Haxe classes. This section provides a guide-level explanation of the various parts of a library definition, with examples. Further detail can be found in later sections.

Libraries

The APIs of native libraries consist of a set of exported functions. An ammer library definition should list these functions and adapt their signatures to Haxe types. Library definitions can also expose constants.

Read on: Library definition

-

Library datatypes

In addition to functions, libraries often define their own datatypes which group together data in a meaningful way. In C, these correspond to pointers to struct types.

-

Read on: Library datatype definition

+

Datatypes

In addition to functions, libraries often define their own datatypes which group together data in a meaningful way. In C, these correspond to pointers to struct types, opaque pointers, enum types, or union types.

+

Read on: Library datatype definition

- « Previous: Troubleshooting + « Previous: Getting started Next: Library definition » \ No newline at end of file diff --git a/index.html b/index.html index 6612d84..02782f8 100644 --- a/index.html +++ b/index.html @@ -2,27 +2,141 @@ Introduction – ammer manual + +

ammer

- -

Introduction

ammer is a Haxe 4 library which brings native libraries (.dll, .dylib, .so) to a variety of Haxe targets without requiring the user to manually write similar but slightly different extern definitions and target-specific stub/glue code.

-

It is intended to be a tool for Haxe library creators. The goal is for end-users to be able to install a C library and its corresponding ammer library, then be able to use the C library in Haxe code on any ammer-supported platform.

-

Supported platforms

-

See also the detailed feature matrix.

-

Planned platforms

+ +

Introduction

+ Diagram: ammer overview + + + + + + + + + + + + + ammer + + + + Haxe code + + + + + + + + C++ + HashLink + Java + ... + + + + + + + + + + + + hxcpp + HL runtime + JVM + ... + + + + + + + + + + + + C externs + HL FFI + JNI + ... + + + + + + + + native library + + +

ammer is a Haxe library which brings native libraries (.dll, .dylib, .so) to a variety of Haxe targets without requiring the user to manually write similar but slightly different extern definitions and target-specific stub/glue code.

+

It is intended to be a tool for Haxe library creators. The goal is for end-users to be able to install a native library and its corresponding ammer library, then be able to use the native library in Haxe code on any ammer-supported platform.

- Next: Getting started » + Next: Overview » \ No newline at end of file diff --git a/intro-installation.html b/intro-installation.html index 66ff9a9..b3ffcdb 100644 --- a/intro-installation.html +++ b/intro-installation.html @@ -2,24 +2,30 @@ Installation – ammer manual + +

ammer

- +

Installation

ammer can be installed as a git library:

-
$ haxelib git ammer git@github.com:Aurel300/ammer.git
-# or
-$ haxelib git ammer https://github.com/Aurel300/ammer.git
-

Alternatively, the Github repository can be cloned and ammer can be installed as a dev library:

-
$ git clone git@github.com:Aurel300/ammer.git
-$ cd ammer
-$ haxelib dev ammer .
-

ammer requires that a C compiler toolkit is installed. Any GCC-compatible compiler should work, as well as MSVC. make or nmake (when using MSVC) is used to invoke the compiler. Each target may have additional dependencies – see target details.

+
# using SSH
+$ haxelib git ammer git@github.com:Aurel300/ammer.git
+# or using HTTPS
+$ haxelib git ammer https://github.com/Aurel300/ammer.git

Alternatively, the Github repository can be cloned manually and ammer can be installed as a dev library:

+
$ git clone git@github.com:Aurel300/ammer.git
+$ cd ammer
+$ haxelib dev ammer .

ammer requires a C compiler toolchain to be installed. Any GCC-compatible compiler should work, as well as MSVC. Each target may have additional dependencies — see target details.

- « Previous: Getting started - Next: Sample project » + « Previous: Why ammer? + Next: Getting started » \ No newline at end of file diff --git a/intro-overview.html b/intro-overview.html new file mode 100644 index 0000000..0a54cb5 --- /dev/null +++ b/intro-overview.html @@ -0,0 +1,87 @@ + + Overview – ammer manual + + + + + +

ammer

+ +

Overview

This document aims to be the definitive, exhaustive documentation for the ammer project and its associated repositories (ammer-core, HaxeAmmer/amlib-*). Knowledge of the Haxe language is assumed (see the Haxe manual), as well as some knowledge of the C language.

+

The sections are organised as follows:

+ +
+ « Previous: Introduction + Next: Terminology » + + \ No newline at end of file diff --git a/intro-sample.html b/intro-sample.html deleted file mode 100644 index 6252b41..0000000 --- a/intro-sample.html +++ /dev/null @@ -1,19 +0,0 @@ - - Sample project – ammer manual - - - -

ammer

- -

Sample project

A sample project is provided with step-by-step build instructions in the samples/poc directory of the main repository.

- - -
- « Previous: Installation - Next: Use cases » - - \ No newline at end of file diff --git a/intro-start.html b/intro-start.html index 5326ca3..183946c 100644 --- a/intro-start.html +++ b/intro-start.html @@ -2,33 +2,36 @@ Getting started – ammer manual + +

ammer

- -

Getting started

To use an existing native library, all that is required is a library definition:

-
class Foobar extends ammer.Library<"foobar"> {
-  public static function repeat(word:String, count:Int):String;
-}
-

The types used in the arguments must be among the supported FFI types. Libraries can define functions, constants, and library datatypes.

-

The functions can then be called like regular static functions:

-
class Main {
-  public static function main():Void {
-    trace(Foobar.repeat("hello", 3));
+	
+	

Getting started

To use an existing native library, all that is required is to write a library definition:

+
class Foobar extends ammer.def.Library<"foobar"> {
+  public static function repeat(word:String, count:Int):String;
+}

The types used in the arguments must be among the supported FFI types. Libraries can define functions, variables, and datatypes. The functions can then be called like regular Haxe functions:

+
class Main {
+  public static function main():Void {
+    trace(Foobar.repeat("hello", 3));
   }
-}
-

During compilation, the ammer haxelib must be added in addition to library-specific configuration:

-
--library ammer
--D ammer.lib.foobar.include=include
--D ammer.lib.foobar.library=lib
---main Main
---hl out.hl
-

A variety of configuration flags can be defined, see the configuration section.

+}

During compilation, the ammer haxelib must be used. Library-specific configuration can be added either using metadata or define flags. The define flags must include at least a build path (used for intermediate files) and an output path (where the ammer-generated dynamic libraries will be placed):

+
--library ammer
+-D ammer.buildPath=build
+-D ammer.outputPath=bin
+--main Main
+--hl bin/out.hl

A variety of configuration flags can be provided; see configuration for more details.

- « Previous: Introduction - Next: Installation » + « Previous: Installation + Next: Definition » \ No newline at end of file diff --git a/intro-terminology.html b/intro-terminology.html new file mode 100644 index 0000000..d2d3a2b --- /dev/null +++ b/intro-terminology.html @@ -0,0 +1,44 @@ + + Terminology – ammer manual + + + + + +

ammer

+ +

Terminology

In the context of Haxe and its use with ammer, terms such as "native" or "library" can be ambiguous. Throughout this document, the terms will have the following meaning:

+
    +
  • native library — Native libraries is typically distributed as .dll (on Windows), .dylib (on macOS), or .so (on Linux). Usually such libraries are written in a system language such as C, and compiled into machine code "native" to a particular architecture or operating system. +
  • +
  • Haxe library — Haxe libraries are packages containing Haxe code, distributed via haxelib, Github, or other means. +
  • +
  • ammer library — A subset of the previous, ammer libraries are Haxe libraries made using ammer.
  • +
  • library — One the above. Should only be used when the context makes it clear which one is meant!
  • +
  • ammer library definition — To create an ammer library, a "definition" is needed, consisting of specially annotated Haxe classes and methods, as described in the Definition section.
  • +
  • extern — Haxe allows marking classes and other types as externs (see the Externs section in the Haxe manual), which allows non-Haxe code (such as functions written in Javascript) to be used safely from within Haxe code.
  • +
  • target — The Haxe compiler compiles Haxe code into one of its various targets, such as C#, Javascript, or HashLink. However, this is not precise enough: it is also important to know how the resulting code is compiled and how it will be executed. In this document, "target" refers to such a more precise combination of target language + runtime platform.
      +
    • Examples: Javascript on Node.js, HashLink in HL/C mode.
    • +
    +
  • +
  • FFI — Foreign Function Interface. On targets with an interpreter (such as Node.js/V8) or a virtual machine (such as the JVM) this generally refers to a mechanism that allows code to interact with native libraries.
  • +
+

With the above in mind, ammer is a Haxe library which is used to create ammer libraries. Typically, their function is to make a native library usable from Haxe. The author of an ammer library creates a library definition corresponding to the API of a native library. Although ammer uses externs under the hood (on some targets), this is not directly visible; in other words, ammer library definitions aim to be a more general concept than externs.

+
+ « Previous: Overview + Next: Why ammer? » + + \ No newline at end of file diff --git a/intro-troubleshooting.html b/intro-troubleshooting.html deleted file mode 100644 index 01ab2f7..0000000 --- a/intro-troubleshooting.html +++ /dev/null @@ -1,17 +0,0 @@ - - Troubleshooting – ammer manual - - - -

ammer

- -

Troubleshooting

Please try to build the sample project first. The sample README includes a troubleshooting section which describes the solutions to some common problems. If the problem still persists, please open an issue.

-
- « Previous: Use cases - Next: Definition » - - \ No newline at end of file diff --git a/intro-use.html b/intro-use.html index 2278222..b83c8e6 100644 --- a/intro-use.html +++ b/intro-use.html @@ -1,29 +1,142 @@ - Use cases – ammer manual + Why ammer? – ammer manual + +

ammer

- -

Use cases

- -
    -
  • expanding the Haxe ecosystem with high quality libraries
      -
    • adding scripting support to Haxe projects with embeddable languages like Lua
    • -
    • adding native UI to Haxe projects
    • -
    -
  • -
  • writing performance-intensive code in C, then using it in Haxe
      -
    • compiling against platforms like CUDA with C code
    • -
    -
  • -
+ +

Why ammer?

+ Diagram: ammer overview + + + + + + + + + + + + + ammer + + + + Haxe code + + + + + + + + C++ + HashLink + Java + ... + + + + + + + + + + + + hxcpp + HL runtime + JVM + ... + + + + + + + + + + + + C externs + HL FFI + JNI + ... + + + + + + + + native library + + +

Unlike Haxe externs and manually written glue code, ammer definitions provide a unified interface: the same definition can be used for C++, for HashLink, for Node.js, etc. Additionally, writing externs and glue code is extremely error-prone and tedious, and requires detailed knowledge of the FFI mechanism used by each platform. ammer aims to hide this technical complexity, allowing library authors to focus purely on the API of the library they are defining. Any necessary externs and glue code is generated automatically. Any issues that are identified in this process can be fixed once, to the benefit of all ammer libraries.

+

ammer can be seen as an extension of the "Haxe promise": write code once and run it anywhere. With ammer this is true also for code that interacts with native libraries, which is crucial for real-world codebases.

- « Previous: Sample project - Next: Troubleshooting » + « Previous: Terminology + Next: Installation » \ No newline at end of file diff --git a/library.html b/library.html deleted file mode 100644 index da243be..0000000 --- a/library.html +++ /dev/null @@ -1,29 +0,0 @@ - - Native library development – ammer manual - - - -

ammer

- -

Native library development

General notes about dynamic libraries

If you are creating a native library from scratch, ensure that it is compiled as a dynamic library. See the sample project makefiles (Windows, OS X, and Linux) for the compiler configuration necessary to correctly produce a dynamic library (.dll, .dylib, and .so, respectively).

-

To actually use a dynamic library at run-time, it must be present in a place in which the OS will know to look. This differs from platform to platform:

-
    -
  • Windows - DLLs in the current working directory will be used
  • -
  • OS X - the dynamic linker will look in /usr/lib, /usr/local/lib, paths specified in the environment variables DYLD_LIBRARY_PATH, DYLD_FALLBACK_LIBRARY_PATH, DYLD_VERSIONED_LIBRARY_PATH, the special @executable_path, and more (see https://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html)
      -
    • during development, run the executable as DYLD_LIBRARY_PATH=<path to where the .dylib is> <run project>
    • -
    -
  • -
  • Linux - the dynamic linker will look in /usr/lib, /usr/local/lib, paths specified in the environment variables LD_LIBRARY_PATH, and possibly more
      -
    • during development, run the executable as LD_LIBRARY_PATH=<path to where the .so is> <run project>
    • -
    -
  • -
-
- « Previous: Lua - Next: Implementation details » - - \ No newline at end of file diff --git a/ref-annot.html b/ref-annot.html new file mode 100644 index 0000000..af7f0dc --- /dev/null +++ b/ref-annot.html @@ -0,0 +1,70 @@ + + List of annotations – ammer manual + + + + + +

ammer

+ +

List of annotations

Metadata which do not correspond to a configuration flag are listed here.

+ +
+

@:ammer.alloc

Allows allocation and deallocation of the annotated struct type using ammer.Lib.allocStruct and ammer.Lib.freeStruct, respectively. See allocation and deallocation.

+
+

@:ammer.c.cast(type:String)

Marks that the annotated argument should be cast to the given C type before being passed to the native call.

+
+

@:ammer.c.macroCall

(Alias: @:ammer.macroCall)

+

Marks the annotated function as a macro call. See macro calls.

+
+

@:ammer.c.prereturn(code:String)

Adds the given C code into the native function, before the return expression. The arguments to the native call are available in the _arg0, ..., _argN local variables. See customising the C code.

+
+

@:ammer.c.return(code:String)

Uses the given C expression instead of the return expression. The arguments to the native call are available in the _arg0, ..., _argN local variables. The string %CALL%, if used in code, will be replaced with the original return expression. See customising the C code.

+
+

@:ammer.derive(e:Expr)


+

@:ammer.gen.alloc(name:String)

Specifies the name for the generated static allocation function. See allocation and deallocation.

+
+

@:ammer.gen.free(name:String)

Specifies the name for the generated instance deallocation function. See allocation and deallocation.

+
+

@:ammer.gen.nullPtr(name:String)

Specifies the name for the generated static null pointer function. See allocation and deallocation.

+
+

@:ammer.haxe

Allows the annotated function to have a Haxe body, skipping ammer processing. See pure Haxe functions.

+
+

@:ammer.native(name:String)

Specifies the native name of the annotated function or field.

+
+

@:ammer.nativePrefix(prefix:String)

Specifies the prefix for native names. The native name will be derived as "prefix" + "the field name", unless overridden on the field itself with @:ammer.native.

+
+

@:ammer.ret.derive(e:Expr, ct:Type)


+

@:ammer.skip

Marks the given function argument to be skipped for the underlying native call.

+
+

@:ammer.sub(sub:Type)

Marks the given type sub as a "subdefinition" of the annotated library. See linking subdefinitions.

+
+ « Previous: List of configuration flags + Next: amlib » + + \ No newline at end of file diff --git a/ref-def.html b/ref-def.html new file mode 100644 index 0000000..f5767e0 --- /dev/null +++ b/ref-def.html @@ -0,0 +1,99 @@ + + ammer.def.* types – ammer manual + + + + + +

ammer

+ +

ammer.def.* types

The types in the ammer.def package are all "marker" types: the types themselves have no meaning and should not be used directly, but they are used as super types for ammer definitions. Any Haxe class that extends one of the types below will be processed by ammer.

+

About the parent:Lib type parameter

The types listed below are written with parent:Lib as a type parameter. This indicates that the type parameter should be filled in with the type name of a type that itself extends ammer.def.Library. This indicates that the given type is the "parent" of the one being declared. See linking subdefinitions.

+
+

ammer.def.Library<id:String>

Library definition. See library definition for examples.

+

Type parameters

    +
  • id:String — The identifier used for this library. This identifier is used in the library configuration, so it must only consist of letters and underscores. It must be unique.
  • +
+

Allowed fields

+

Applicable metadata

+
+

ammer.def.Opaque<type:String, parent:Lib>

Opaque type definition. See opaque type definition for examples.

+

Type parameters

    +
  • type:String — The C name of this opaque type. This can be any valid C type declaration, which may contain spaces or asterisks.
  • +
  • parent:Libparent library.
  • +
+

Allowed fields

+

Applicable metadata

+
+

ammer.def.Struct<type:String, parent:Lib>

Struct definition. See struct definition for examples.

+

Type parameters

    +
  • type:String — The C name of this struct. This can be any valid C type declaration, which may contain spaces or asterisks. Note that although the type that extends ammer.def.Struct represents a pointer to the struct, the final asterisk should not be written in this type parameter.
  • +
  • parent:Libparent library.
  • +
+

Allowed fields

+

Applicable metadata

+
+

ammer.def.Sublibrary<parent:Lib>

Sublibrary definition. See sublibrary definition for examples.

+

Type parameters

+

Allowed fields

+

Applicable metadata

+
+ « Previous: FFI types + Next: ammer.Lib » + + \ No newline at end of file diff --git a/ref-ffi.html b/ref-ffi.html new file mode 100644 index 0000000..e787bb7 --- /dev/null +++ b/ref-ffi.html @@ -0,0 +1,241 @@ + + FFI types – ammer manual + + + + + +

ammer

+ +

FFI types

This section summarises the types that can be used in definitions for function signatures and field types. The types are split into multiple categories:

+ +

In each category, the table shows the following information:

+
    +
  • Description — What the type represents.
  • +
  • Ammer type — How to write the type in definitions.
  • +
  • Haxe call type — What the type will look like from a Haxe client of the ammer library.
  • +
  • Haxe shortcut — Convenience alias for the type using an existing Haxe type, if any.
  • +
  • C type — What the type maps to in a native library/in C language.
  • +
+

With a small number of exceptions, the ammer.ffi.* types exist solely for defining the types of a native library's functions or fields. When an ammer library is used from regular Haxe code, these types turn into a standard Haxe type, the conversion happens automatically. The exceptions are:

+
    +
  • ammer.ffi.Array
  • +
  • ammer.ffi.Box
  • +
  • ammer.ffi.Bytes
  • +
  • ammer.ffi.Haxe
  • +
+

Primitive types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionAmmer typeHaxe call typeHaxe shortcutC type
Voidammer.ffi.VoidVoidVoidvoid
Booleanammer.ffi.BoolBoolBoolbool
Unsigned 8-bit integerammer.ffi.UInt8UInt-uint8_t
Unsigned 16-bit integerammer.ffi.UInt16UInt-uint16_t
Unsigned 32-bit integerammer.ffi.UInt32UIntUIntuint32_t
Unsigned 64-bit integerammer.ffi.UInt64UInt-uint64_t
Signed 8-bit integerammer.ffi.Int8Int-int8_t
Signed 16-bit integerammer.ffi.Int16Int-int16_t
Signed 32-bit integerammer.ffi.Int32IntIntint32_t
Signed 64-bit integerammer.ffi.Int64Inthaxe.Int64int64_t
Single-precision IEEE 754 numberammer.ffi.Float32Single 1Single 1float
Double-precision IEEE 754 numberammer.ffi.Float64FloatFloatdouble
Stringammer.ffi.StringStringStringconst char*
+

1: Single

Single is only available on some Haxe targets. When a Float32 is used on a target that does not natively support single-precision floating-points, a lossy conversion is used from 64 bits.

+

Library datatypes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionAmmer typeHaxe shortcutC type
Opaque pointer, struct pointer-T extends Struct ...(type)*
Opaque data, structammer.ffi.Deref<T>T extends Struct ...(type)
Opaque data, structammer.ffi.Alloc<T>T extends Struct ...(type)
Haxe objectammer.ffi.Haxe<T>Tvoid*
+

Composed types

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionAmmer typeHaxe shortcutC type
A contiguous arrayammer.ffi.Array<T>-(type)*
Boxammer.ffi.Box<T>-(type)*
Callbackammer.ffi.Callback<...>--
+

Special/marker types

+ + + + + + + + + + + + + + +
Ammer typeMeaning
ammer.ffi.ThisStands for the current struct instance, see instance methods
ammer.ffi.Unsupported<...>An unsupported type: the type parameter (a string constant) will be passed to native calls.
+

Standard library types

+ + + + + + + + + + + + +
DescriptionAmmer typeC type
File pointerammer.ffi.FilePtrFILE*
+
+ « Previous: Reference + Next: ammer.def.* types » + + \ No newline at end of file diff --git a/ref-flags.html b/ref-flags.html new file mode 100644 index 0000000..6f54d4e --- /dev/null +++ b/ref-flags.html @@ -0,0 +1,140 @@ + + List of configuration flags – ammer manual + + + + + +

ammer

+ +

List of configuration flags

Note that the _ after lib. in all the names below should be replaced by the identifier of the library.

+ +
+

ammer.buildPath:String

Path used for intermediate build artefacts. These include the C glue code generated by ammer, as well as compiled binary objects, before they are packaged into dynamic libraries. See paths.

+

Compile-time defines

    +
  • -D ammer.buildPath=(string) — sets the build path.
  • +
+
+

ammer.debug:String

Sets the debug mode for ammer. The value is a comma-separated list of categories of debug messages to show. The available categories are:

+
    +
  • stage
  • +
  • stage-ffi
  • +
+

The flag can be set to the string all to enable all of the above.

+

Compile-time defines

    +
  • -D ammer.debug=(comma-separated list) — sets the debug mode.
  • +
+
+

ammer.outputPath:String

Path used for final build products. These are dynamic libraries compiled by ammer that would typically be deployed with the program using them. See paths.

+

Compile-time defines

    +
  • -D ammer.outputPath=(string) — sets the output path.
  • +
+
+

ammer.lib._.defines:Array<String>

List of C preprocessor directives to set when compiling the library.

+

Compile-time defines

    +
  • -D ammer.lib._.define=(string) — adds one entry to the list.
  • +
  • -D ammer.lib._.defines=(comma-separated list) — adds multiple entries to the list.
  • +
+

Metadata (on a library definition)

    +
  • @:ammer.lib.define(define:String) — adds one entry to the list.
  • +
  • @:ammer.lib.defines(defines:Array<String>) — adds multiple entries to the list.
  • +
+
+

ammer.lib._.frameworks:Array<String>

List of frameworks to use when compiling the library. Only has an effect on macOS.

+

Compile-time defines

    +
  • -D ammer.lib._.framework=(string) — adds one entry to the list.
  • +
  • -D ammer.lib._.frameworks=(comma-separated list) — adds multiple entries to the list.
  • +
+

Metadata (on a library definition)

    +
  • @:ammer.lib.framework(framework:String) — adds one entry to the list.
  • +
  • @:ammer.lib.frameworks(frameworks:Array<String>) — adds multiple entries to the list.
  • +
+
+

ammer.lib._.headers.includes:Array<SourceInclude>

List of headers to include when compiling the library. There are four different include styles:

+
    +
  • IncludeLocal#include "header.h"
  • +
  • IncludeGlobal#include <header.h>
  • +
  • ImportLocal#import "header.h"
  • +
  • ImportGlobal#import <header.h>
  • +
+

Compile-time defines

    +
  • -D ammer.lib._.headers=(comma-separated list) — adds multiple entries to the list, as IncludeLocals.
  • +
  • -D ammer.lib._.headers.includeLocal=(string) — adds one entry to the list, as IncludeLocal.
  • +
  • -D ammer.lib._.headers.includeGlobal=(string) — adds one entry to the list, as IncludeGlobal.
  • +
  • -D ammer.lib._.headers.importLocal=(string) — adds one entry to the list, as ImportLocal.
  • +
  • -D ammer.lib._.headers.importGlobal=(string) — adds one entry to the list, as ImportGlobal.
  • +
+

Metadata (on a library definition)

    +
  • @:ammer.lib.headers.include(header:String) — adds one entry to the list, as IncludeLocal.
  • +
  • @:ammer.lib.headers.import(header:String) — adds one entry to the list, as ImportLocal.
  • +
  • @:ammer.lib.headers.includeLocal(header:String) — adds one entry to the list, as IncludeLocal.
  • +
  • @:ammer.lib.headers.includeGlobal(header:String) — adds one entry to the list, as IncludeGlobal.
  • +
  • @:ammer.lib.headers.importLocal(header:String) — adds one entry to the list, as ImportLocal.
  • +
  • @:ammer.lib.headers.importGlobal(header:String) — adds one entry to the list, as ImportGlobal.
  • +
+
+

ammer.lib._.includePaths:Array<String>

Paths to provide to the C compiler as "include paths", which are used when searching for header files.

+

Compile-time defines

    +
  • -D ammer.lib._.includePaths=(comma-separated list) — adds multiple entries to the list.
  • +
+

Metadata (on a library definition)

    +
  • @:ammer.lib.includePath(path:String) — adds one entry to the list.
  • +
  • @:ammer.lib.includePaths(paths:Array<String>) — adds multiple entries to the list.
  • +
+
+

ammer.lib._.language:LibraryLanguage

Specifies the language of the native library. This language is also used for generating the glue code. Possible values:

+
    +
  • C - C
  • +
  • Cpp - C++
  • +
  • ObjC - Objective-C
  • +
  • ObjCpp - Objective-C++
  • +
+

Compile-time defines

    +
  • -D ammer.lib._.language=(string) — sets the language.
  • +
+

Metadata (on a library definition)

    +
  • @:ammer.lib.language(language:LibraryLanguage) — sets the language.
  • +
+
+

ammer.lib._.libraryPaths:Array<String>

Paths to provide to the C compiler (more accurately, the linker) as "library paths", which are used when searching for library files (.dll, .dylib, .so files).

+

Compile-time defines

    +
  • -D ammer.lib._.libraryPaths=(comma-separated list) — adds multiple entries to the list.
  • +
+

Metadata (on a library definition)

    +
  • @:ammer.lib.libraryPath(path:String) — adds one entry to the list.
  • +
  • @:ammer.lib.libraryPaths(paths:Array<String>) — adds multiple entries to the list.
  • +
+
+

ammer.lib._.linkNames:Array<String>

Names of libraries to link against when compiling this native library. Should not include prefixes such as -l or lib.

+

Compile-time defines

    +
  • -D ammer.lib._.linkNames=(comma-separated list) — adds multiple entries to the list.
  • +
+

Metadata (on a library definition)

    +
  • @:ammer.lib.linkName(path:String) — adds one entry to the list.
  • +
  • @:ammer.lib.linkNames(paths:Array<String>) — adds multiple entries to the list.
  • +
+
+ « Previous: ammer.Lib + Next: List of annotations » + + \ No newline at end of file diff --git a/ref-lib.html b/ref-lib.html new file mode 100644 index 0000000..9892e92 --- /dev/null +++ b/ref-lib.html @@ -0,0 +1,46 @@ + + ammer.Lib – ammer manual + + + + + +

ammer

+ +

ammer.Lib

The ammer.Lib type provides a number of methods for client interaction with ammer libraries. These methods are (by necessity) macro methods. As a result, their signatures displayed below are only approximations.

+
+

ammer.Lib.allocStruct(type:Class<Struct>, ?initialValues:{ ... }):Struct

Allocates a struct of the given type, optionally assigning the given initial values to its fields. The type must be annotated with the @:ammer.alloc metadata.

+

Arguments

    +
  • type — The name (or full path) of the type to allocate.
  • +
  • initialValues — An object literal where the keys and values correspond to fields and their initial values, respectively.
  • +
+
+

ammer.Lib.createHaxeRef(type:Class<T>, value:T):ammer.ffi.Haxe<T>

Creates a reference to the given Haxe value. See Haxe types.

+

Arguments

    +
  • type — The name (or full path) of the Haxe type. This is required to make sure there are no unexpected type mismatch problems e.g. when passing references to anonymous structures.
  • +
  • value — The Haxe value to create a reference to.
  • +
+
+

ammer.Lib.freeStruct(instance:Struct):Void

Deallocates the given pointer. The type must be annotated with the @:ammer.alloc metadata.

+

Arguments

    +
  • instance — The value to deallocate.
  • +
+
+

ammer.Lib.nullPtrStruct(type:Class<Struct>):Struct

Returns a null pointer of the given type.

+

Arguments

    +
  • type — The name (or full path) of the type.
  • +
+
+ « Previous: ammer.def.* types + Next: List of configuration flags » + + \ No newline at end of file diff --git a/ref.html b/ref.html new file mode 100644 index 0000000..f53731d --- /dev/null +++ b/ref.html @@ -0,0 +1,31 @@ + + Reference – ammer manual + + + + + +

ammer

+ +

Reference

FFI types

Haxe types do not map one-to-one to C types. Types in the ammer.ffi package are used to provide additional context.

+

Read on: FFI types

+

ammer.def.* types

ammer definitions, such as library definitions, are declared as Haxe classes which extend one of the marker types in the ammer.def package.

+

Read on: ammer.def.* types

+

ammer.Lib

Client code using ammer libraries might need to perform operations which do not correspond to native library methods, but rather utility calls such as allocation.

+

Read on: ammer.Lib

+

List of configuration flags

Read on: List of configuration flags

+

List of annotations

Read on: List of annotations

+
+ « Previous: Python + Next: FFI types » + + \ No newline at end of file diff --git a/search.js b/search.js new file mode 100644 index 0000000..223809a --- /dev/null +++ b/search.js @@ -0,0 +1,81 @@ +/*! https://github.com/leeoniya/uFuzzy (v1.0.6) */ +var uFuzzy=function(){"use strict";const e=new Intl.Collator("en").compare,t=1/0,l=/(?:\s+|^)-[a-z\d]+/gi,n={unicode:!1,interSplit:"[^A-Za-z0-9']+",intraSplit:"[a-z][A-Z]",intraBound:"[A-Za-z][0-9]|[0-9][A-Za-z]|[a-z][A-Z]",interLft:0,interRgt:0,interChars:".",interIns:t,intraChars:"[a-z\\d']",intraIns:0,intraContr:"'[a-z]{1,2}\\b",intraMode:0,intraSlice:[1,t],intraSub:0,intraTrn:0,intraDel:0,intraFilt:()=>!0,sort:(t,l)=>{let{idx:n,chars:r,terms:i,interLft2:s,interLft1:a,start:g,intraIns:f,interIns:h}=t;return n.map(((e,t)=>t)).sort(((t,u)=>r[u]-r[t]||f[t]-f[u]||i[u]+s[u]+.5*a[u]-(i[t]+s[t]+.5*a[t])||h[t]-h[u]||g[t]-g[u]||e(l[n[t]],l[n[u]])))}},r=(e,l)=>0==l?"":1==l?e+"??":l==t?e+"*?":e+`{0,${l}}?`,i="(?:\\b|_)";function s(e){e=Object.assign({},n,e);const{unicode:t,interLft:s,interRgt:a,intraMode:f,intraSlice:h,intraIns:u,intraSub:c,intraTrn:o,intraDel:p,intraContr:m,intraSplit:b,interSplit:d,intraBound:x,intraChars:R}=e;let S=t?"u":"",{intraRules:I}=e;null==I&&(I=e=>{let t=n.intraSlice,l=0,r=0,i=0,s=0,a=e.length;return a>4?(t=h,l=u,r=c,i=o,s=p):3>a||(i=Math.min(o,1),4==a&&(l=Math.min(u,1))),{intraSlice:t,intraIns:l,intraSub:r,intraTrn:i,intraDel:s}});let A=!!b,z=RegExp(b,"g"+S),E=RegExp(d,"g"+S),k=RegExp("^"+d+"|"+d+"$","g"+S),C=RegExp(m,"gi"+S);const L=e=>(e=e.replace(k,"").toLowerCase(),A&&(e=e.replace(z,(e=>e[0]+" "+e[1]))),e.split(E).filter((e=>""!=e))),y=(t,l=0,n=!1)=>{let g=L(t);if(0==g.length)return[];let h,c=Array(g.length).fill("");if(g=g.map(((e,t)=>e.replace(C,(e=>(c[t]=e,""))))),1==f)h=g.map(((e,t)=>{let{intraSlice:l,intraIns:n,intraSub:i,intraTrn:s,intraDel:a}=I(e);if(n+i+s+a==0)return e+c[t];let[g,f]=l,h=e.slice(0,g),u=e.slice(f),o=e.slice(g,f);1==n&&1==h.length&&h!=o[0]&&(h+="(?!"+h+")");let p=o.length,m=[e];if(i)for(let e=0;p>e;e++)m.push(h+o.slice(0,e)+R+o.slice(e+1)+u);if(s)for(let e=0;p-1>e;e++)o[e]!=o[e+1]&&m.push(h+o.slice(0,e)+o[e+1]+o[e]+o.slice(e+2)+u);if(a)for(let e=0;p>e;e++)m.push(h+o.slice(0,e+1)+"?"+o.slice(e+1)+u);if(n){let e=r(R,1);for(let t=0;p>t;t++)m.push(h+o.slice(0,t)+e+o.slice(t)+u)}return"(?:"+m.join("|")+")"+c[t]}));else{let e=r(R,u);2==l&&u>0&&(e=")("+e+")("),h=g.map(((t,l)=>t.split("").map(((e,t,l)=>(1==u&&0==t&&l.length>1&&e!=l[t+1]&&(e+="(?!"+e+")"),e))).join(e)+c[l]))}let o=2==s?i:"",p=2==a?i:"",m=p+r(e.interChars,e.interIns)+o;return l>0?n?h=o+"("+h.join(")"+p+"|"+o+"(")+")"+p:(h="("+h.join(")("+m+")(")+")",h="(.??"+o+")"+h+"("+p+".*)"):(h=h.join(m),h=o+h+p),[RegExp(h,"i"+S),g,c]},j=(e,t,l)=>{let[n]=y(t);if(null==n)return null;let r=[];if(null!=l)for(let t=0;l.length>t;t++){let i=l[t];n.test(e[i])&&r.push(i)}else for(let t=0;e.length>t;t++)n.test(e[t])&&r.push(t);return r};let w=!!x,M=RegExp(d,S),Z=RegExp(x,S);const D=(t,l,n)=>{let[r,i,g]=y(n,1),[f]=y(n,2),h=i.length,u=t.length,c=Array(u).fill(0),o={idx:Array(u),start:c.slice(),chars:c.slice(),terms:c.slice(),interIns:c.slice(),intraIns:c.slice(),interLft2:c.slice(),interRgt2:c.slice(),interLft1:c.slice(),interRgt1:c.slice(),ranges:Array(u)},p=1==s||1==a,m=0;for(let n=0;t.length>n;n++){let u=l[t[n]],c=u.match(r),b=c.index+c[1].length,d=b,x=!1,R=0,I=0,A=0,z=0,E=0,k=0,C=0,L=0,y=[];for(let t=0,l=2;h>t;t++,l+=2){let n=c[l].toLowerCase(),r=i[t]+g[t],f=r.length,o=n.length,m=n==r;if(!m&&c[l+1].length>=f){let e=c[l+1].toLowerCase().indexOf(r);e>-1&&(y.push(d,e,f),d+=T(c,l,e,f),n=r,o=f,m=!0,0==t&&(b=d))}if(p||m){let e=d-1,t=d+o,i=!0,g=!0;if(-1==e||M.test(u[e]))m&&R++;else{if(2==s){x=!0;break}if(w&&Z.test(u[e]+u[e+1]))m&&I++;else{if(1==s){let e=c[l+1],t=d+o;if(e.length>=f){let i,s=0,a=!1,g=RegExp(r,"ig"+S);for(;i=g.exec(e);){s=i.index;let e=t+s,l=e-1;if(-1==l||M.test(u[l])){R++,a=!0;break}if(Z.test(u[l]+u[e])){I++,a=!0;break}}if(a){y.push(d,s,f),d+=T(c,l,s,f),n=r,o=f,m=!0;break}}x=!0;break}i=!1}}if(t==u.length||M.test(u[t]))m&&A++;else{if(2==a){x=!0;break}if(w&&Z.test(u[t-1]+u[t]))m&&z++;else{if(1==a){x=!0;break}g=!1}}m&&(E+=f,i&&g&&k++)}if(o>f&&(L+=o-f),t>0&&(C+=c[l-1].length),!e.intraFilt(r,n,d)){x=!0;break}h-1>t&&(d+=o+c[l+1].length)}if(!x){o.idx[m]=t[n],o.interLft2[m]=R,o.interLft1[m]=I,o.interRgt2[m]=A,o.interRgt1[m]=z,o.chars[m]=E,o.terms[m]=k,o.interIns[m]=C,o.intraIns[m]=L,o.start[m]=b;let e=u.match(f),l=o.ranges[m]=[],r=e.index+e[1].length,i=r,s=r,a=y.length,g=a>0?0:1/0,h=a-3;for(let t=2;e.length>t;t++){let n=e[t].length;if(g>h||y[g]!=r)r+=n;else{let l=y[g+2],s=y[g+1]+l;r+=n+s,i=r-l,e[t+1]=e[t+1].slice(s),g+=3}t%2==0?s=r:n>0&&(l.push(i,s),i=s=r)}s>i&&l.push(i,s),m++}}if(t.length>m)for(let e in o)o[e]=o[e].slice(0,m);return o},T=(e,t,l,n)=>{let r=e[t]+e[t+1].slice(0,l);return e[t-1]+=r,e[t]=e[t+1].slice(l,l+n),e[t+1]=e[t+1].slice(l+n),r.length};return{search:(...t)=>((t,n,r=!1,i=1e3,s)=>{let a=null,f=null,h=[];n=n.replace(l,(e=>(h.push(e.trim().slice(1)),"")));let u,c=L(n);if(h.length>0){if(u=RegExp(h.join("|"),"i"+S),0==c.length){let e=[];for(let l=0;t.length>l;l++)u.test(t[l])||e.push(l);return[e,null,null]}}else if(0==c.length)return[null,null,null];if(r){let e=L(n);if(e.length>1){let l=e.slice().sort(((e,t)=>t.length-e.length));for(let e=0;l.length>e;e++){if(0==s?.length)return[[],null,null];s=j(t,l[e],s)}a=g(e).map((e=>e.join(" "))),f=[];let n=new Set;for(let e=0;a.length>e;e++)if(s.length>n.size){let l=s.filter((e=>!n.has(e))),r=j(t,a[e],l);for(let e=0;r.length>e;e++)n.add(r[e]);f.push(r)}else f.push([])}}null==a&&(a=[n],f=[s?.length>0?s:j(t,n)]);let o=null,p=null;if(h.length>0&&(f=f.map((e=>e.filter((e=>!u.test(t[e])))))),i>=f.reduce(((e,t)=>e+t.length),0)){o={},p=[];for(let l=0;f.length>l;l++){let n=f[l];if(null==n||0==n.length)continue;let r=a[l],i=D(n,t,r),s=e.sort(i,t,r);if(l>0)for(let e=0;s.length>e;e++)s[e]+=p.length;for(let e in i)o[e]=(o[e]??[]).concat(i[e]);p=p.concat(s)}}return[[].concat(...f),o,p]})(...t),split:L,filter:j,info:D,sort:e.sort}}const a=(()=>{let e={A:"ÁÀÃÂÄĄ",a:"áàãâäą",E:"ÉÈÊËĖ",e:"éèêëę",I:"ÍÌÎÏĮ",i:"íìîïį",O:"ÓÒÔÕÖ",o:"óòôõö",U:"ÚÙÛÜŪŲ",u:"úùûüūų",C:"ÇČ",c:"çč",N:"Ñ",n:"ñ",S:"Š",s:"š"},t=new Map,l="";for(let n in e)e[n].split("").forEach((e=>{l+=e,t.set(e,n)}));let n=RegExp(`[${l}]`,"g"),r=e=>t.get(e);return e=>{if("string"==typeof e)return e.replace(n,r);let t=Array(e.length);for(let l=0;e.length>l;l++)t[l]=e[l].replace(n,r);return t}})();function g(e){let t,l,n=(e=e.slice()).length,r=[e.slice()],i=Array(n).fill(0),s=1;for(;n>s;)s>i[s]?(t=s%2&&i[s],l=e[s],e[s]=e[t],e[t]=l,++i[s],s=1,r.push(e.slice())):(i[s]=0,++s);return r}const f=(e,t)=>t?`${e}`:e,h=(e,t)=>e+t;return s.latinize=a,s.permute=e=>g([...Array(e.length).keys()]).sort(((e,t)=>{for(let l=0;e.length>l;l++)if(e[l]!=t[l])return e[l]-t[l];return 0})).map((t=>t.map((t=>e[t])))),s.highlight=function(e,t,l=f,n="",r=h){n=r(n,l(e.substring(0,t[0]),!1))??n;for(let i=0;t.length>i;i+=2)n=r(n,l(e.substring(t[i],t[i+1]),!0))??n,t.length-3>i&&(n=r(n,l(e.substring(t[i+1],t[i+2]),!1))??n);return r(n,l(e.substring(t[t.length-1]),!1))??n},s}(); +document.addEventListener("DOMContentLoaded", () => { + let haystackPromise = null; + let haystack = null; + let haystackPlain = null; + let fuzzy = null; + function loadFuzzy() { + if (fuzzy !== null) return fuzzy; + return fuzzy = new uFuzzy({}); + } + function loadHaystack() { + if (haystackPromise !== null) return haystackPromise; + return haystackPromise = new Promise(async (resolve) => { + let res = await fetch("search.json"); + haystack = await res.json(); + haystackPlain = haystack.map(page => page[4]); + resolve(); + }); + } + const searchEl = document.getElementById("search"); + const menuSplits = document.querySelectorAll("#menu .menu-split"); + searchEl.addEventListener("focus", loadHaystack); + let existingQuery = null; + let lastOp = 0; + searchEl.addEventListener("input", () => { + if (existingQuery !== null) { + clearTimeout(existingQuery); + existingQuery = null; + } + const query = searchEl.value.trim(); + const queryOp = ++lastOp; + existingQuery = setTimeout(() => { + if (query === "") { + menuSplits[0].classList.remove("show"); + menuSplits[1].classList.add("show"); + } else { + menuSplits[0].innerText = "Searching..."; + menuSplits[0].classList.add("show"); + menuSplits[1].classList.remove("show"); + loadHaystack().then(() => { + if (queryOp !== lastOp) return; + const [idxs, info, order] = loadFuzzy().search(haystackPlain, query); + if (!order || order.length === 0) { + menuSplits[0].innerText = "No results found!"; + } else { + menuSplits[0].innerHTML = "
    " + order.map(i => { + const infoIdx = order[i]; + const resultIdx = info.idx[infoIdx]; + const found = haystack[resultIdx]; + let title = found[2]; + if (found[3]) { + title = `${title} — ${found[3]}`; + } + let url = found[0] + ".html"; + if (found[1]) { + url = `${url}#${found[1]}`; + } + const plain = found[4]; + const ranges = info.ranges[infoIdx]; + const range = [ranges[0], ranges[ranges.length - 1]]; + const ctx = 35; + let preEl = ""; + let postEl = ""; + let rangeBefore = [range[0] - ctx, range[0]]; + if (rangeBefore[0] < 0) rangeBefore[0] = 0; + else preEl = "…"; + let rangeAfter = [range[1], range[1] + ctx]; + if (rangeAfter[1] >= plain.length) rangeAfter[1] = plain.length; + else postEl = "…"; + const pre = plain.substring(...rangeBefore); + const post = plain.substring(...rangeAfter); + const snippet = plain.substring(...range); + return `
  • ${title}
    "${preEl}${pre}${snippet}${post}${preEl}"
  • `; + }).join("") + "
"; + } + }); + } + }, 200); + }); +}); diff --git a/search.json b/search.json new file mode 100644 index 0000000..8240f52 --- /dev/null +++ b/search.json @@ -0,0 +1 @@ +[["intro-overview",null,"Overview",null,"Overview\nThis document aims to be the definitive, exhaustive documentation for the ammer project and its associated repositories ( ammer-core, HaxeAmmer/amlib-*). Knowledge of the Haxe language is assumed (see the Haxe manual ), as well as some knowledge of the C language.\nThe sections are organised as follows:\nIntroduction — General overview. Overview\nTerminology\nWhy ammer?\nInstallation\nGetting started\n\nDefinition — Guide-level explanation of writing library definitions using ammer. Library definition\nDatatypes\n\nConfiguration — Guide-level explanation of library configuration. Providing flags\nProject-wide configuration\nLibrary configuration\n\nTarget details — Target-specific information. Feature parity\nC++\nC#\nEval\nHashLink (both JIT and HL/C)\nJava (both Java and JVM)\nLua\nNeko\nNode.js\nPython\n\nReference — Full reference of the available APIs, metadata, and ammer types. FFI types\nammer.def.* types\nammer.Lib\nList of configuration flags\nList of annotations\n\namlib — Writing and publishing ammer libraries. Conventions\nCI\nBaking\n\nAdvanced topics — More advanced considerations when writing library definitions. Type cycles\nGarbage collection\nString encoding\nStatic and dynamic linking\nPackaging and distribution\nPerformance\n\nammer-core — About the underlying framework. Interface\nImplementing new platforms\n\n"],["intro-terminology",null,"Terminology",null,"Terminology\nIn the context of Haxe and its use with ammer, terms such as \"native\" or \"library\" can be ambiguous. Throughout this document, the terms will have the following meaning:\nnative library — Native libraries is typically distributed as .dll (on Windows), .dylib (on macOS), or .so (on Linux). Usually such libraries are written in a system language such as C, and compiled into machine code \"native\" to a particular architecture or operating system. Examples: libPNG , SDL 2 , libuv .\n\nHaxe library — Haxe libraries are packages containing Haxe code, distributed via haxelib , Github, or other means. Examples: HaxeUI , OpenFL , pecan .\n\nammer library — A subset of the previous, ammer libraries are Haxe libraries made using ammer.\nlibrary — One the above. Should only be used when the context makes it clear which one is meant !\nammer library definition — To create an ammer library, a \"definition\" is needed, consisting of specially annotated Haxe classes and methods, as described in the Definition section .\nextern — Haxe allows marking classes and other types as externs (see the Externs section in the Haxe manual), which allows non-Haxe code (such as functions written in Javascript) to be used safely from within Haxe code.\ntarget — The Haxe compiler compiles Haxe code into one of its various targets, such as C#, Javascript, or HashLink. However, this is not precise enough: it is also important to know how the resulting code is compiled and how it will be executed. In this document, \"target\" refers to such a more precise combination of target language + runtime platform. Examples: Javascript on Node.js, HashLink in HL/C mode.\n\nFFI — Foreign Function Interface. On targets with an interpreter (such as Node.js/V8) or a virtual machine (such as the JVM) this generally refers to a mechanism that allows code to interact with native libraries.\nWith the above in mind, ammer is a Haxe library which is used to create ammer libraries. Typically, their function is to make a native library usable from Haxe. The author of an ammer library creates a library definition corresponding to the API of a native library. Although ammer uses externs under the hood (on some targets), this is not directly visible; in other words, ammer library definitions aim to be a more general concept than externs.\n"],["intro-use",null,"Why ammer?",null,"Why ammer?\nUnlike Haxe externs and manually written glue code, ammer definitions provide a unified interface: the same definition can be used for C++, for HashLink, for Node.js, etc. Additionally, writing externs and glue code is extremely error-prone and tedious, and requires detailed knowledge of the FFI mechanism used by each platform. ammer aims to hide this technical complexity, allowing library authors to focus purely on the API of the library they are defining. Any necessary externs and glue code is generated automatically. Any issues that are identified in this process can be fixed once, to the benefit of all ammer libraries.\nammer can be seen as an extension of the \"Haxe promise\": write code once and run it anywhere. With ammer this is true also for code that interacts with native libraries, which is crucial for real-world codebases.\n"],["intro-installation",null,"Installation",null,"Installation\nammer can be installed as a git library:\n# using SSH\n$ haxelib git ammer git@github.com:Aurel300/ammer.git\n# or using HTTPS\n$ haxelib git ammer https://github.com/Aurel300/ammer.git\nAlternatively, the Github repository can be cloned manually and ammer can be installed as a dev library:\n$ git clone git@github.com:Aurel300/ammer.git\n$ cd ammer\n$ haxelib dev ammer .\nammer requires a C compiler toolchain to be installed. Any GCC-compatible compiler should work, as well as MSVC. Each target may have additional dependencies — see target details .\n"],["intro-start",null,"Getting started",null,"Getting started\nTo use an existing native library, all that is required is to write a library definition :\nclass Foobar extends ammer.def.Library<\"foobar\"> {\n public static function repeat(word:String, count:Int):String;\n}\nThe types used in the arguments must be among the supported FFI types . Libraries can define functions , variables , and datatypes . The functions can then be called like regular Haxe functions:\nclass Main {\n public static function main():Void {\n trace(Foobar.repeat(\"hello\", 3));\n }\n}\nDuring compilation, the ammer haxelib must be used. Library-specific configuration can be added either using metadata or define flags. The define flags must include at least a build path (used for intermediate files) and an output path (where the ammer-generated dynamic libraries will be placed):\n--library ammer\n-D ammer.buildPath=build\n-D ammer.outputPath=bin\n--main Main\n--hl bin/out.hl\nA variety of configuration flags can be provided; see configuration for more details.\n"],["definition",null,"Definition",null,"Definition\nAn ammer library is a set of library definitions and library datatype definitions. Since Haxe organises code into modules and classes, both libraries and library datatypes are defined using Haxe classes. This section provides a guide-level explanation of the various parts of a library definition, with examples. Further detail can be found in later sections.\nLibraries\nThe APIs of native libraries consist of a set of exported functions. An ammer library definition should list these functions and adapt their signatures to Haxe types. Library definitions can also expose constants.\nRead on: Library definition\nDatatypes\nIn addition to functions, libraries often define their own datatypes which group together data in a meaningful way. In C, these correspond to pointers to struct types, opaque pointers, enum types, or union types.\nRead on: Library datatype definition\n"],["definition-library",null,"Library definition",null,"Library definition\nTo define a library, extend ammer.def.Library<...> with a Haxe class. The type parameter for ammer.def.Library should be a string identifier for the native library. This identifier is used in the library configuration , so it must only consist of letters and underscores.\nExample: library definition\npackage foo;\n\nclass Foobar extends ammer.def.Library<\"foobar\"> {\n // ...\n}\nIn this example, foo.Foobar is an ammer library definition for the native library called foobar. A library definition typically includes metadata which configures properties such as the include path, the language of the native library, headers to use, etc. See configuration for more details.\nThe fields of a library definition consist of functions and variables . Libraries can also be split up into several classes, see sublibraries .\nMetadata applicable to library definitions\nMetadata can be attached to the library definition class. This allows for configuration of the library compilation, its source language, header files, and more. See the full metadata descriptions for more information:\n@:ammer.lib.define\n@:ammer.lib.framework\n@:ammer.lib.frameworks\n@:ammer.lib.includePath\n@:ammer.lib.includePaths\n@:ammer.lib.language\n@:ammer.lib.libraryPath\n@:ammer.lib.libraryPaths\n@:ammer.lib.linkName\n@:ammer.lib.linkNames\n@:ammer.lib.headers.include\n@:ammer.lib.headers.import\n@:ammer.lib.headers.includeLocal\n@:ammer.lib.headers.importLocal\n@:ammer.lib.headers.includeGlobal\n@:ammer.lib.headers.importGlobal\n@:ammer.nativePrefix\n@:ammer.sub\n"],["definition-library-functions",null,"Functions",null,"Functions\nFunctions can be declared in library definitions using public static fuction fields with no function body (similar to Haxe externs).\nExample: function in library definition\nclass Foobar extends ammer.def.Library<\"foobar\"> {\n public static function hello(a:Int, b:String):Float;\n}\nIn this example, hello is a function in the Foobar library. The function maps to the native function double hello(int a, char *b) (in C types).\nAll return types and argument types must be written explicitly, since Haxe type inference is not compatible with native libraries. Only a subset of Haxe types can be used. See FFI types .\n"],["definition-library-functions","macros","Functions","Macros","Macros\nThe same public static function syntax can be used to declare C preprocessor macro calls, but the additional metadata @:ammer.macroCall should be applied. Macros which require unusual C syntax may cause a compilation failure: for arbitrary C code expressions, see the next section .\n"],["definition-library-functions","custom-c","Functions","Customising the C code","Customising the C code\nFor every method declared in an ammer definition, there is glue code generated which has the following general shape:\ntarget_return_type func(args...) {\n native_args = ... // \"pre\": decode arguments from target-specific representation to C\n ... // \"prereturn\"\n c_return_type _return =\n native_call(native_args...); // \"return\"\n ... // \"post\": encode returned value to a target-specific representation, cleanup, return\n}\nA large part of the function, including its exact signature, depends on the concrete target. However, ammer ensures that the initial part of the function code gets the local variables to the same state on any platform: the local variables _arg0, ..., _argN are of the C types corresponding to the declared argument types.\nIf there is additional code that should be called before the actual native call happens, it can be inserted at the point marked \"prereturn\" above. This is accomplished with the @:ammer.c.prereturn metadata.\nIf the native call itself should be replaced with a different C expression, this can be accomplished with the @:ammer.c.return metadata. The substring %CODE% will be replaced in the provided code with the original call expression.\n"],["definition-library-functions","pure-haxe","Functions","Pure Haxe functions","Pure Haxe functions\nThe @:ammer.haxe metadata can be used to define methods on libraries which are implemented purely in Haxe and have no native counterpart. When this metadata is attached to a method (and only then), it may have a body.\nMetadata applicable to functions\nMetadata can be used to inject additional C code into the wrapper code, mark functions as macro calls, or provide the native name for a function. See the full metadata descriptions for more information:\n@:ammer.haxe\n@:ammer.macroCall\n@:ammer.native\n@:ammer.c.macroCall\n@:ammer.c.prereturn\n@:ammer.c.return\n@:ammer.ret.derive\nThe following metadata can be attached to function arguments:\n@:ammer.skip\n@:ammer.derive\n@:ammer.c.cast\n"],["definition-library-variables",null,"Variables",null,"Variables\nVariables can be declared in library definitions using public static var fields.\nExample: variable in library definition\nclass Foobar extends ammer.def.Library<\"foobar\"> {\n public static var bar:Int;\n}\nIn this example, bar is an integer variable in the Foobar library.\nAs for function signatures, variable types are restricted to a subset of Haxe types. See FFI types .\n"],["definition-library-variables","constants","Variables","Constants","Constants\nIf a value from a native library is available immediately, such as constants or macro definitions, it can be declared as a constant in the ammer definition using a public static final field.\nExample: constant in library definition\nclass Foobar extends ammer.def.Library<\"foobar\"> {\n @:ammer.native(\"HELLO_WORLD\")\n public static final helloWorld:String;\n}\nIn this example, helloWorld is a string constant for the Foobar ammer library definition. The headers of the foobar native library must ensure that HELLO_WORLD is a valid C expression, for example with #define HELLO_WORLD \"hello world\".\n@:ammer.native can be used to specify the C expression which will be used to determine the value of a constant. There is no restriction to what the expression can be: it may be a literal, a constant, the result of a library call, and so forth. However, all constant values are initialised at the same time, typically before Haxe main is reached, so the C expression should not be a mutable value, because it will not be updated.\nMetadata applicable to variables and constants\n@:ammer.native\n"],["definition-sub",null,"Sublibraries",null,"Sublibraries\nFor better code organisation, it is possible to split a library definition into multiple classes. If the separate class consists of static functions and not \"instance\" methods (in which case a library datatype definition might be more appropriate), it can be defined as a sublibrary.\nTo define a sublibrary, extend ammer.def.Sublibrary<...> with a Haxe class. The type parameter for ammer.def.Sublibrary should be the ammer library this class belongs to.\nExample: sublibrary definition\n@:ammer.sub((_ : FoobarSub))\nclass Foobar extends ammer.def.Library<\"foobar\"> {}\n\nclass FoobarSub extends ammer.def.Sublibrary {\n // ...\n}\nIn this example, FoobarSub is a sublibrary belonging to Foobar.\nApart from forming a separate Haxe class, sublibraries behave identically to libraries .\nLinking\nSublibraries should be linked with the parent library using the @:ammer.sub(...) metadata to avoid compilation errors. See linking subdefinitions .\nMetadata applicable to sublibraries\n@:ammer.nativePrefix\n@:ammer.sub\n"],["definition-type",null,"Datatypes",null,"Datatypes\nLibraries often group data into complex types such as structs. To make use of these in Haxe code and in ammer library definitions, they can be defined as Haxe types.\nOpaque types\nOpaque types are types whose fields and layout are only known to the library that defines them. Any interaction with such types happens through methods defined by the library.\nRead on: Opaque types\nStructs\nStructs are types which contain fields, which can be read from or written to.\nRead on: Structs\nEnums\nEnums are sets of named values of the same type.\nRead on: Enums\nHaxe types\nNative libraries can store pointers to instances of Haxe types.\nRead on: Haxe types\nCallbacks\nCallbacks allow Haxe code to be called by the native library.\nRead on: Callbacks\n"],["definition-type-opaque",null,"Opaque types",null,"Opaque types\nWhen a native library uses a type in its API without revealing the actual fields and layout of that type (as is the case with structs ), the type can be called opaque. Such values cannot be allocated or freed, and can only be used meaningfully by passing them to the methods of the native library that defined them in the first place.\nTo define an opaque type, extend ammer.def.Opaque<...> with a Haxe class. The first type parameter for ammer.def.Opaque should be a string identifying the native C type name. The second type parameter should be the ammer library this type belongs to.\nAlthough opaque type definitions cannot contain any variable fields, they may still contain instance methods .\nExample: opaque type definition\nclass FoobarOpaque extends ammer.def.Opaque<\"opaque_t\", Foobar> {\n // ...\n}\nIn this example, FoobarOpaque is an opaque type of the Foobar library. The C name for this type is opaque_t.\nLinking\nOpaque types should be linked with the parent library using the @:ammer.sub(...) metadata to avoid compilation errors. See linking subdefinitions .\nMetadata applicable to opaque types\n@:ammer.nativePrefix\nNot yet implemented: large opaque types\nCurrently, ammer assumes every opaque type is pointer-sized or smaller. This allows passing it between Haxe and native code without any allocations. Supporting opaque types that do not fit into a pointer is a planned feature.\n"],["definition-type-struct",null,"Structs",null,"Structs\nWhen a struct type is not opaque , its fields are known and can be read and written directly, without using a library method.\nTo define a struct type, extend ammer.def.Struct<..., ...> with a Haxe class. The first type parameter for ammer.def.Struct should be a string identifying the native C type name. The second type parameter should be the ammer library this type belongs to.\nStruct definitions can contain variable fields , as well as instance methods .\nExample: library datatype definition\nclass FoobarStruct extends ammer.def.Struct<\"struct foobar_s\", Foobar> {\n // ...\n}\nIn this example, FoobarStruct is a struct in the Foobar library. The C name for this struct is struct foobar_s. Values of FoobarStruct in Haxe represent instances of struct foobar_s* (a pointer to struct foobar_s).\n"],["definition-type-struct","pointer","Structs","Instances are pointers","Instances are pointers\nNote that on the Haxe side, any struct value will be represented as a pointer to a struct. This is because most ammer targets do not support arbitrarily large stack-allocated data. See passing structs directly for declaring APIs which do not use a pointer indirection.\n"],["definition-type-struct","variables","Structs","Variables","Variables\nStructs definitions can contain variables, declared as public var or var fields.\nExample: struct variables\nclass FoobarStruct extends ammer.def.Struct<\"struct foobar_s\", Foobar> {\n public var bar:Int;\n}\nIn this example FoobarStruct has a bar variable that can be read or written:\nvar x:FoobarStruct = #dummy expr/*...*/;\nx.bar = 3;\nvar y = x.bar;\nVariables map to pointer accesses in C code, so a bar variable is read as (someStruct)->bar and written as (someStruct)->bar = value. Note that any read or write variable access may have a runtime cost of a function call.\n"],["definition-type-struct","alloc","Structs","Allocation and deallocation","Allocation and deallocation\nTo make it possible to allocate and deallocate a struct, it must be marked with the @:ammer.alloc metadata. When annotated, several functions are made available:\nalloc — a static function which allocates an instance of the given struct type. Initial values for its fields can optionally be passed using an object syntax.\nfree — an instance method which deallocates the underlying allocation.\nnullPtr — a static function which returns a null pointer of the given struct type.\nThe name of the generated functions can be changed to avoid conflicts with other functions. @:ammer.alloc is simply a convenience shortcut to the combination @:ammer.gen.alloc(\"alloc\"), @:ammer.gen.free(\"free\"), @:ammer.gen.nullPtr(\"nullPtr\"), where the string arguments specify the name of each generated method.\nExample: allocating and deallocating a struct\nGiven a struct definition annotated with @:ammer.alloc:\n@:ammer.alloc\nclass FoobarStruct extends ammer.def.Struct<\"struct foobar_s\", Foobar> {\n public var some_field:Int;\n}\nIt can be allocated by calling alloc:\n// with fields zeroed out:\nvar x = FoobarStruct.alloc();\n// or with some initial values:\nvar x = FoobarStruct.alloc({\n some_field: 42,\n});\nIt can then be deallocated:\nx.free();\nAnd a null pointer can be obtained:\nvar x = FoobarStruct.nullPtr();\n"],["definition-type-struct","deref","Structs","Passing structs directly","Passing structs directly\nNative methods which take a struct directly, as opposed to a pointer to a struct, can be declared by using the special ammer.ffi.Deref<...> type. This dereferences the struct pointer just before the native method call.\nExample: using ammer.ffi.Deref\nclass Foobar {\n public static function take_struct_ptr(x:FoobarStruct):Void;\n public static function take_struct_val(x:ammer.ffi.Deref):Void;\n}\nThis example demonstrates passing a struct using a pointer and passing it directly. The corresponding C signatures could look like this:\nvoid take_struct_ptr(struct foobar_s* x) { /*...*/ }\nvoid take_struct_val(struct foobar_s x) { /*...*/ }\nNote that on the Haxe call side, the two methods are called the same way: by passing an instance of the FoobarStruct type. The dereferencing, if any, happens transparently.\nvar x:FoobarStruct = #dummy expr/*...*/;\nFoobar.take_struct_ptr(x);\nFoobar.take_struct_val(x);\nA similar situation arises when a native library method returns a struct value. To obtain a pointer to the struct, a heap allocation must take place to store that struct. In ammer, return types can be wrapped with the special ammer.ffi.Alloc<...> type to achieve this.\nExample: using ammer.ffi.Alloc\nclass Foobar {\n public static function give_struct_ptr():FoobarStruct;\n public static function give_struct_val():ammer.ffi.Alloc;\n}\nThis example demonstrates a native method returning a pointer to a struct and one returning a struct directly. The corresponding C signatures could look like this:\nstruct foobar_s* give_struct_ptr() { /*...*/ }\nstruct foobar_s give_struct_val() { /*...*/ }\nNote that on the Haxe call side, the two methods have the same return type: an instance of FoobarStruct. The allocation, if any, happens transparently.\nvar x:FoobarStruct = Foobar.give_struct_ptr();\nvar y:FoobarStruct = Foobar.give_struct_val();\nLinking\nStructs should be linked with the parent library using the @:ammer.sub(...) metadata to avoid compilation errors. See linking subdefinitions .\nMetadata applicable to structs\n@:ammer.alloc\n@:ammer.nativePrefix\n@:ammer.sub\n@:ammer.gen.alloc\n@:ammer.gen.free\n@:ammer.gen.nullPtr\n"],["definition-type-instance",null,"Instance methods",null,"Instance methods\nAlthough C does not have the concept of instance methods (unlike, for example, Java or C++), native libraries often define APIs which simulate such a feature by passing a pointer to a struct or opaque type as the first argument.\nIn ammer, it is possible to use such methods as instance methods rather than static methods, resulting in more readable client code. To achieve this, a function must be declared in an opaque type definition or a struct definition with two requirements:\nIt must be declared as a function (and not a static function); and\none of its arguments must be of the special ammer.ffi.This type.\nWhen calling instance methods declared this way, the This argument is omitted, as it is automatically filled in.\nExample: instance method\nclass FoobarStruct extends ammer.def.Struct<\"struct foobar_s\", Foobar> {\n public function do_something(_:ammer.ffi.This, a:Int):Int;\n}\nIn this example, do_something is an instance method. In Haxe code, it could be used like this:\nvar x:FoobarStruct = #dummy expr/*...*/;\nx.do_something(42);\nNote that the first argument for do_something is not specified – x is used automatically.\n"],["definition-type-enum",null,"Enums",null,"Enums\nEnums are sets of distinct, named values of the same type. In C, this may be an actual enum declaration , or even a set of defines. Importantly, the values of an enum should be known at compile time.\nTo define an enum type, add @:build(ammer.def.Enum.build(..., ..., ...)) to a Haxe enum abstract. The first argument parameter for ammer.def.Enum.build should be a string identifying the native C type name. The second argument should be an FFI type . The third argument should be the ammer library this type belongs to.\nEnums should only contain variable declarations, one for each enum variant.\nExample: enum definition\n@:build(ammer.def.Enum.build(\"int\", Int32, Foobar))\nenum abstract FoobarEnum(Int) from Int to Int {\n @:ammer.native(\"FOOBAR_VAL1\") var Val1;\n @:ammer.native(\"FOOBAR_VAL2\") var Val2;\n // ...\n}\nIn this example, FoobarEnum is an enum in the Foobar library. The C type underlying this enum is a regular int. There are two variants: Val1 and Val2, which have the integer values available in the constants FOOBAR_VAL1 and FOOBAR_VAL2 at compile time.\nCompilation\nIn order for Haxe to be able to use ammer enums like regular enum abstracts, the value of each variant must be known at compile time. ammer will automatically extract the appropriate values by invoking the C compiler.\nLinking\nEnums should be linked with the parent library using the @:ammer.sub(...) metadata to avoid compilation errors. See linking subdefinitions .\n"],["definition-type-haxe",null,"Haxe types",null,"Haxe types\nC libraries often contain struct fields or function arguments of type void*, such that client code using the library can provide a pointer to its own datatypes. In ammer, such void* values can stand for instances of a Haxe type, such as a Haxe class instance.\nGarbage collection\nAll Haxe targets are garbage collected, which means it is the runtime's responsibility to understand which instances are no longer needed and can be re-used to free memory. For Haxe programs which do not interact with native libraries, this is not a problem. However, as soon as a Haxe instance is passed to a native library, a problem may arise: the Haxe runtime could decide that the Haxe instance is no longer usable, so it could be freed, but a reference to it may still be obtainable via the native library.\nThe solution used in ammer is to wrap Haxe instances with a reference counter, such that the programmer can indicate when a Haxe instance is or is not in use. To pass Haxe types to native libraries, use the ammer.ffi.Haxe<...> type in ammer definitions. When calling such functions, instances of Haxe types must first be wrapped using the ammer.Lib.createHaxeRef function. The resulting value has a value field to obtain the underlying Haxe instance, as well as an incref and decref function to increment or decrement the reference counter respectively.\nThe initial reference count of a Haxe reference is 0.\nExample: function accepting a Haxe type\nclass MyHaxeType { /*...*/ }\n\nclass Foobar extends ammer.def.Library<\"foobar\"> {\n public static function hello(a:ammer.ffi.Haxe):Void;\n}\nIn this example, MyHaxeType is a regular Haxe class. The hello function of the Foobar library accepts an instance of MyHaxeType.\nvar x:MyHaxeType = #dummy expr/*...*/;\nvar xr = ammer.Lib.createHaxeRef(xr);\nxr.incref();\nFoobar.hello(xr);\nxr.decref();\n"],["definition-type-callbacks",null,"Callbacks",null,"Callbacks\nCallbacks allow native libraries to call Haxe code, for example, to invoke a handler when an event happens. Callbacks in C generally belong to two categories:\nStatic callbacks — the native library stores a function pointer directly.\nCallbacks with context — the native library stores a function pointer, as well as an additional void* value which is passed back to the function.\nIn ammer, a callback is declared using the ammer.ffi.Callback<...> type, which has 5 type parameters:\nammer.ffi.Callback<\n CallbackType,\n FunctionType,\n CallTarget,\n CallArgs,\n Lib\n>\nThe type parameters should be filled in as follows:\nCallbackType — The function type as seen by the native library.\nFunctionType — The function type as seen by Haxe.\nCallTarget — An expression (wrapped in square brackets) to reach the void* value representing the callback context, or \"global\".\nCallArgs — An array of expressions representing the arguments to pass to the Haxe function.\nLib — The parent ammer library.\nIt may be convenient to typedef callback types when referring to them within ammer definitions.\nExample: declaring and using a callback type\nAssuming a C library with the following implementation:\n// Type alias for the function type.\n// It receives two integer arguments, in addition to the user-defined context.\nint32_t (* callback_type)(int32_t, int32_t, void*);\n\nstatic callback_type *stored_fptr = NULL;\nstatic void *stored_context = NULL;\n\nvoid store_callback(callback_type *fptr, void *call_context) {\n stored_fptr = fptr;\n stored_context = call_context;\n}\n\nint32_t invoke_callback(int32_t a, int32_t b) {\n return stored(a, b, stored_context);\n}\nThe callback type can be reflected in ammer as follows:\ntypedef CallbackType = ammer.ffi.Callback<\n (ammer.ffi.Int32, ammer.ffi.Int32, Haxe<(Int, Int)->Int>)->ammer.ffi.Int32,\n (Int, Int)->Int,\n [arg2],\n [arg0, arg1],\n Foobar\n>;\nNote that [arg2] refers to the third, void*-typed argument of callback_type, whereas [arg0, arg1] refer to the first two, int-typed arguments.\nThe ammer definition for the C library above may look like this:\nclass Foobar extends ammer.def.Library<\"foobar\"> {\n public static function store_callback(_:CallbackType, _:ammer.ffi.Haxe<(Int, Int)->Int>):Void;\n public static function invoke_callback(_:ammer.ffi.Int32, _:ammer.ffi.Int32):ammer.ffi.Int32;\n}\nFinally, an example of using the library to invoke the callback:\nvar func = (a:Int, b:Int) -> { return a + b; };\nvar funcRef = ammer.Lib.createHaxeRef(func);\nfuncRef.incref();\nFoobar.store_callback(funcRef);\n\n// ...\n\ntrace(Foobar.invoke_callback(1, 2)); // 3\nNote the use of createHaxeRef: func is an instance of a Haxe type, thus it must be wrapped with a reference counter as explained in the Haxe types section .\n"],["definition-link",null,"Linking subdefinitions",null,"Linking subdefinitions\nIn addition to libraries , ammer offers four kinds of \"subdefinitions\":\nSublibraries\nOpaque types\nStructs\nEnums\nEach declaration declares a link to the parent library (e.g. ... extends ammer.Sublibrary). However, a corresponding backlink should also be declared on the parent library, using the @:ammer.sub metadata. Although this declaration is optional (for the time being), it is recommended to avoid certain compilation errors, especially if the subdefinitions are declared in separate files. See type cycles for a technical explanation.\nExample: linking a sublibrary\n// in file Foobar.hx\n@:ammer.sub((_ : FoobarSub))\nclass Foobar extends ammer.def.Library<\"foobar\"> {}\n\n// in file FoobarSub.hx\nclass FoobarSub extends ammer.def.Sublibrary {}\nIn this example, Foobar links to its sublibrary using the @:ammer.sub metadata. FoobarSub links to its parent library using the type parameter of ammer.def.Sublibrary.\n"],["configuration",null,"Configuration",null,"Configuration\nIn addition to library definitions consisting of annotated Haxe classes, an ammer library must be configured such that it can be compiled properly. This section provides a guide-level explanation of the different aspects of ammer configuration, with examples. Further detail can be found in later sections.\nProviding flags\nMost configuration flags can be set using metadata or using compile-time defines.\nRead on: Providing flags\nProject-wide configuration\nammer requires a few flags to be set for the project as a whole before compilation can proceed.\nRead on: Project-wide configuration\nLibrary configuration\nLibraries can be configured to include particular header files, to use certain paths as the include/library paths for the C compiler, to define C preprocessor values, and so forth.\nRead on: Library configuration\n"],["configuration-providing",null,"Providing flags",null,"Providing flags\nA \"configuration flag\" in this document refers to a string key, such as ammer.buildPath associated to a value of a given type, such as String. Most configuration flags can be set using two ways:\nEither by annotating a library definition with metadata; or\nby providing a compile-time define when invoking the Haxe compiler.\nFor configuration flags associated to a particular library (for example: \"which header files should be included when compiling this library\"), using metadata is the more natural option. The relevant metadata are written in the same file as the definition of the library itself, which means information is not spread across too many places. Nevertheless, defines can be used to override the library behaviour on a per-project basis.\nConfiguration flags which are not associated to any library can only be provided using defines.\nExample: providing flags\n@:ammer.lib.headers.include(\"png.h\")\nclass LibPng extends ammer.def.Library<\"png\"> {\n // ...\n}\nIn this example, the LibPng library is configured to include the png.h header file during compilation using metadata. Alternatively, the metadata can be omitted, and the flag provided using a compile-time define:\n-D ammer.lib.png.headers.include=png.h\nNote the naming convention: in the metadata case, the metadata is attached directly to the LibPng class, so providing the png identifier as part of the metadata name would be redundant. On the other hand, the compile-time define must specify which library it is referring to by using the png identifier as part of the define name.\n"],["configuration-project",null,"Project-wide configuration",null,"Project-wide configuration\nWhen building a project that uses an ammer library there are two flags which are required: the build and output paths . Other, optional flags, allow enabling the debug mode for ammer, setting target-specific options , or configuring the build system .\n"],["configuration-project","paths","Project-wide configuration","Paths","Paths\nThere are two paths that need to be configured before ammer can continue compilation.\nThe build path, configured using #lang-hxml -D ammer.buildPath, specifies a path used as an intermediate directory. During compilation, ammer creates C files containing the glue code required to use a native library with the currently selected Haxe target. These files, as well as the intermediate outputs of the C compiler, are all placed into the build path. The build path is created if it does not exist.\nThe output path, configured using #lang-hxml -D ammer.outputPath, specifies the path for the resulting ammer-built dynamic libraries, which are files with the extensions .dll, .so, .dylib, .hdll, or .ndll. These files must be distributed with the final executable for the library to function properly.\n"],["configuration-project","debug","Project-wide configuration","Debug mode","Debug mode\nFull debug logging for ammer can be enabled using #lang-hxml -D ammer.debug=all. During compilation, this will cause a lot of additional output that may be useful for ammer-debugging purposes.\n"],["configuration-project","target","Project-wide configuration","Target-specific configuration","Target-specific configuration\nThe configuration flags specific to each target are described in the target details section. These flags are prefixed with the target they apply to. For example, ammer.hl. is the prefix for all HashLink-specific configuration flags.\n"],["configuration-project","build","Project-wide configuration","Build system configuration","Build system configuration\n(TODO)\n"],["configuration-library",null,"Library configuration",null,"Library configuration\nConfiguration flags specific to a library are typically provided by annotating the library definition with metadata, although they can be overridden on a per-project basis using defines (see providing flags ).\n"],["configuration-library","includes","Library configuration","Includes","Includes\nThe API of C libraries, consisting of function signatures and types, is typically made available by including a header file.\nExample: including a header file\n@:ammer.lib.headers.include(\"png.h\")\nclass LibPng extends ammer.def.Library<\"png\"> {\n // ...\n}\nIn this example, the LibPng library is configured to include the png.h header file during compilation using metadata. This corresponds to the C code:\n#include \"png.h\"\nThere are different styles of includes, see @:ammer.lib.headers.includes.\n"],["configuration-library","link-names","Library configuration","Link names","Link names\nThe @:ammer.lib.linkName metadata configures the name(s) of the dynamic library that ammer should link against such that native functions are available. This corresponds to the GCC flag -l.\nExample: setting the link name\n@:ammer.lib.linkName(\"png\")\nclass LibPng extends ammer.def.Library<\"png\"> {\n // ...\n}\nIn this example, the LibPng library is configured to link against the png dynamic library. The C compiler will receive the argument -lpng.\nUnless configured otherwise, an ammer library uses its identifier as the link name. Some libraries (e.g. \"header-only\" libraries where the implementation is enabled with a preprocessor define ) have no dynamic library to link against: in this case, @:ammer.lib.linkNames([]) can be used to clear the list of link names.\nOn macOS, \"frameworks\" are packages of headers and dynamic libraries. The @:ammer.lib.framework metadata can be used to declare that an ammer library uses a particular framework.\n"],["configuration-library","defines","Library configuration","Defines","Defines\nC preprocessor defines can be enabled for a library using the @:ammer.lib.define metadata.\n"],["configuration-library","paths","Library configuration","Paths","Paths\nWhen resolving header includes and when linking, the compiler needs to know where to look. ammer libraries can be configured with include paths and library paths. These paths correspond to the GCC flags -I and -L, respectively.\nInclude paths can be configured using the @:ammer.lib.includePath metadata, library paths can be configured using the @:ammer.lib.libraryPath metadata.\nBoth include paths and library paths are set relative to the file they are declared in .\nExample: setting the include path\n@:ammer.lib.includePath(\"../../native\")\n@:ammer.lib.headers.include(\"png.h\")\nclass LibPng extends ammer.def.Library<\"png\"> {\n // ...\n}\nAssuming the directory hierarchy is as follows:\nnative/\n png.h\nhaxe/\n src/\n LibPng.hx\nThe compiler will look for the png.h header file in the directory native.\n"],["configuration-library","language","Library configuration","Language","Language\nBy default, ammer generates glue code in the C language. For libraries requiring the use of another language, the language can be changed using the @:ammer.lib.language metadata. Currently supported languages are:\nC - C\nCpp - C++\nObjC - Objective-C\nObjCpp - Objective-C++\n"],["target",null,"Target details",null,"Target details\nammer aims to support all Haxe sys targets , including Javascript compiled with hxnodejs, but excluding PHP. \nFeature parity\nEach ammer target supports the same set of features, unless otherwise noted.\nRead on: Feature parity\nTarget-specific information\nThe rest of this chapter contains information on how each target should be used, its configuration flags, etc.\nRead on:\nC++\nC#\nEval\nHashLink (both JIT and HL/C)\nJava (both Java and JVM)\nLua\nNeko\nNode.js\nPython\n"],["target-feature-parity",null,"Feature parity",null,"Feature parity\n"],["target-feature-parity","shared-buffers","Feature parity","Shared buffers","Shared buffers\nSince each ammer target has a different runtime with different internal representations of core types such as haxe.io.Bytes, some targets do not support directly sharing memory between Haxe code and native code.\nIn the target summaries in the remaining sections, \"Shared buffers\" is one of the following:\nYes - haxe.io.Bytes can be passed directly (without copying) to the native library as a byte pointer and vice versa.\nFrom Haxe to native only - haxe.io.Bytes can be passed directly (without copying) to the native library as a byte pointer but a native byte pointer cannot be used as a haxe.io.Bytes value.\nNo - haxe.io.Bytes must always be copied to get a byte pointer.\n"],["target-feature-parity","shared-vectors","Feature parity","Shared vectors","Shared vectors\nIn the target summaries in the remaining sections, \"Shared vectors\" is one of the following:\nYes - haxe.ds.Vector can be passed directly (without copying) to the native library as a pointer and vice versa.\nFrom Haxe to native only - haxe.ds.Vector can be passed directly (without copying) to the native library as a pointer but a native pointer cannot be used as a haxe.ds.Vector value.\nNo - haxe.ds.Vector must always be copied to get a pointer.\n"],["target-hxcpp",null,"C++",null,"C++\nTarget summary\nFeature | Status |\nShared buffers | Yes |\nShared vectors | Yes |\nConfiguration flags\nammer.cpp.staticLink\n"],["target-hxcpp","flag-staticlink","C++","ammer.cpp.staticLink"," ammer.cpp.staticLink:Bool\nDefaults to true. Note that dynamic linking on C++ is planned, but not yet implemented.\n"],["target-cs",null,"C#",null,"C#\nTarget summary\nFeature | Status |\nShared buffers | From Haxe to native only |\nShared vectors | From Haxe to native only |\nConfiguration flags\n(no additional flags)\n"],["target-eval",null,"Eval",null,"Eval\nFeature | Status |\nShared buffers | No |\nShared vectors | No |\nConfiguration flags\n(no additional flags)\n"],["target-hashlink",null,"HashLink",null,"HashLink\nFeature | Status |\nShared buffers | Yes |\nShared vectors | Yes |\nConfiguration flags\nammer.hl.includePaths\nammer.hl.libraryPaths\n"],["target-hashlink","flag-includepaths","HashLink","ammer.hl.includePaths"," ammer.hl.includePaths:Array\n"],["target-hashlink","flag-librarypaths","HashLink","ammer.hl.libraryPaths"," ammer.hl.libraryPaths:Array\n"],["target-java",null,"Java",null,"Java\nFeature | Status |\nShared buffers | From Haxe to native only |\nShared vectors | From Haxe to native only |\nConfiguration flags\nammer.java.includePaths\nammer.java.libraryPaths\n"],["target-java","flag-includepaths","Java","ammer.java.includePaths"," ammer.java.includePaths:Array\n"],["target-java","flag-librarypaths","Java","ammer.java.libraryPaths"," ammer.java.libraryPaths:Array\n"],["target-lua",null,"Lua",null,"Lua\nFeature | Status |\nShared buffers | No |\nShared vectors | No |\nConfiguration flags\nammer.lua.includePaths\nammer.lua.libraryPaths\n"],["target-lua","flag-includepaths","Lua","ammer.lua.includePaths"," ammer.lua.includePaths:Array\n"],["target-lua","flag-librarypaths","Lua","ammer.lua.libraryPaths"," ammer.lua.libraryPaths:Array\n"],["target-neko",null,"Neko",null,"Neko\nFeature | Status |\nShared buffers | From Haxe to native only |\nShared vectors | No |\nConfiguration flags\nammer.neko.includePaths\nammer.neko.libraryPaths\n"],["target-neko","flag-includepaths","Neko","ammer.neko.includePaths"," ammer.neko.includePaths:Array\n"],["target-neko","flag-librarypaths","Neko","ammer.neko.libraryPaths"," ammer.neko.libraryPaths:Array\n"],["target-nodejs",null,"Node.js",null,"Node.js\nFeature | Status |\nShared buffers | Yes |\nShared vectors | No |\nConfiguration flags\nammer.js.nodeGypBinary\n"],["target-nodejs","flag-nodegypbinary","Node.js","ammer.js.nodeGypBinary"," ammer.js.nodeGypBinary:String\n"],["target-python",null,"Python",null,"Python\nFeature | Status |\nShared buffers | From Haxe to native only |\nShared vectors | No |\nConfiguration flags\nammer.python.version\nammer.python.includePaths\nammer.python.libraryPaths\n"],["target-python","flag-version","Python","ammer.python.version"," ammer.python.version:Int\n"],["target-python","flag-includepaths","Python","ammer.python.includePaths"," ammer.python.includePaths:Array\n"],["target-python","flag-librarypaths","Python","ammer.python.libraryPaths"," ammer.python.libraryPaths:Array\n"],["ref",null,"Reference",null,"Reference\nFFI types\nHaxe types do not map one-to-one to C types. Types in the ammer.ffi package are used to provide additional context.\nRead on: FFI types\nammer.def.* types\nammer definitions, such as library definitions , are declared as Haxe classes which extend one of the marker types in the ammer.def package.\nRead on: ammer.def.* types\nammer.Lib\nClient code using ammer libraries might need to perform operations which do not correspond to native library methods, but rather utility calls such as allocation.\nRead on: ammer.Lib\nList of configuration flags\nRead on: List of configuration flags\nList of annotations\nRead on: List of annotations\n"],["ref-ffi",null,"FFI types",null,"FFI types\nThis section summarises the types that can be used in definitions for function signatures and field types. The types are split into multiple categories:\nPrimitive types\nLibrary datatypes\nComposed types\nSpecial types\nStandard library types\nIn each category, the table shows the following information:\nDescription — What the type represents.\nAmmer type — How to write the type in definitions.\nHaxe call type — What the type will look like from a Haxe client of the ammer library.\nHaxe shortcut — Convenience alias for the type using an existing Haxe type, if any.\nC type — What the type maps to in a native library/in C language.\nWith a small number of exceptions, the ammer.ffi.* types exist solely for defining the types of a native library's functions or fields. When an ammer library is used from regular Haxe code, these types turn into a standard Haxe type, the conversion happens automatically. The exceptions are:\nammer.ffi.Array\nammer.ffi.Box\nammer.ffi.Bytes\nammer.ffi.Haxe\n"],["ref-ffi","primitive","FFI types","Primitive types","Primitive types\nDescription | Ammer type | Haxe call type | Haxe shortcut | C type |\nVoid | ammer.ffi.Void | Void | Void | void |\nBoolean | ammer.ffi.Bool | Bool | Bool | bool |\nUnsigned 8-bit integer | ammer.ffi.UInt8 | UInt | - | uint8_t |\nUnsigned 16-bit integer | ammer.ffi.UInt16 | UInt | - | uint16_t |\nUnsigned 32-bit integer | ammer.ffi.UInt32 | UInt | UInt | uint32_t |\nUnsigned 64-bit integer | ammer.ffi.UInt64 | UInt | - | uint64_t |\nSigned 8-bit integer | ammer.ffi.Int8 | Int | - | int8_t |\nSigned 16-bit integer | ammer.ffi.Int16 | Int | - | int16_t |\nSigned 32-bit integer | ammer.ffi.Int32 | Int | Int | int32_t |\nSigned 64-bit integer | ammer.ffi.Int64 | Int | haxe.Int64 | int64_t |\nSingle-precision IEEE 754 number | ammer.ffi.Float32 | Single 1 | Single 1 | float |\nDouble-precision IEEE 754 number | ammer.ffi.Float64 | Float | Float | double |\nString | ammer.ffi.String | String | String | const char* |\n"],["ref-ffi","fn-single","FFI types","Footnote 1: Single"," 1 : Single\nSingle is only available on some Haxe targets. When a Float32 is used on a target that does not natively support single-precision floating-points, a lossy conversion is used from 64 bits.\n"],["ref-ffi","library","FFI types","Library datatypes","Library datatypes\nDescription | Ammer type | Haxe shortcut | C type |\nOpaque pointer, struct pointer | - | T extends Struct ... | (type)* |\nOpaque data, struct | ammer.ffi.Deref | T extends Struct ... | (type) |\nOpaque data, struct | ammer.ffi.Alloc | T extends Struct ... | (type) |\nHaxe object | ammer.ffi.Haxe | T | void* |\n"],["ref-ffi","composed","FFI types","Composed types","Composed types\nDescription | Ammer type | Haxe shortcut | C type |\nA contiguous array | ammer.ffi.Array | - | (type)* |\nBox | ammer.ffi.Box | - | (type)* |\nCallback | ammer.ffi.Callback<...> | - | - |\n"],["ref-ffi","special","FFI types","Special/marker types","Special/marker types\nAmmer type | Meaning |\nammer.ffi.This | Stands for the current struct instance, see instance methods |\nammer.ffi.Unsupported<...> | An unsupported type: the type parameter (a string constant) will be passed to native calls. |\n"],["ref-ffi","stdlib","FFI types","Standard library types","Standard library types\nDescription | Ammer type | C type |\nFile pointer | ammer.ffi.FilePtr | FILE* |\n"],["ref-def",null,"ammer.def.* types",null,"ammer.def.* types\nThe types in the ammer.def package are all \"marker\" types: the types themselves have no meaning and should not be used directly, but they are used as super types for ammer definitions. Any Haxe class that extends one of the types below will be processed by ammer.\n"],["ref-def","parent","ammer.def.* types","About the parent:Lib type parameter","About the parent:Lib type parameter\nThe types listed below are written with parent:Lib as a type parameter. This indicates that the type parameter should be filled in with the type name of a type that itself extends ammer.def.Library. This indicates that the given type is the \"parent\" of the one being declared. See linking subdefinitions .\n"],["ref-def","library","ammer.def.* types","ammer.def.Library"," ammer.def.Library\nLibrary definition. See library definition for examples.\nType parameters\nid:String — The identifier used for this library. This identifier is used in the library configuration , so it must only consist of letters and underscores. It must be unique.\nAllowed fields\nStatic methods\nStatic variables\nStatic constants\nApplicable metadata\n@:ammer.lib.define\n@:ammer.lib.framework\n@:ammer.lib.frameworks\n@:ammer.lib.includePath\n@:ammer.lib.includePaths\n@:ammer.lib.language\n@:ammer.lib.libraryPath\n@:ammer.lib.libraryPaths\n@:ammer.lib.linkName\n@:ammer.lib.linkNames\n@:ammer.lib.headers.include\n@:ammer.lib.headers.import\n@:ammer.lib.headers.includeLocal\n@:ammer.lib.headers.importLocal\n@:ammer.lib.headers.includeGlobal\n@:ammer.lib.headers.importGlobal\n@:ammer.nativePrefix\n@:ammer.sub\n"],["ref-def","opaque","ammer.def.* types","ammer.def.Opaque"," ammer.def.Opaque\nOpaque type definition. See opaque type definition for examples.\nType parameters\ntype:String — The C name of this opaque type. This can be any valid C type declaration, which may contain spaces or asterisks.\nparent:Lib — parent library .\nAllowed fields\nInstance methods\nApplicable metadata\n@:ammer.nativePrefix\n"],["ref-def","struct","ammer.def.* types","ammer.def.Struct"," ammer.def.Struct\nStruct definition. See struct definition for examples.\nType parameters\ntype:String — The C name of this struct. This can be any valid C type declaration, which may contain spaces or asterisks. Note that although the type that extends ammer.def.Struct represents a pointer to the struct , the final asterisk should not be written in this type parameter.\nparent:Lib — parent library .\nAllowed fields\nInstance methods\nVariables\nApplicable metadata\n@:ammer.alloc\n@:ammer.nativePrefix\n@:ammer.sub\n@:ammer.gen.alloc\n@:ammer.gen.free\n@:ammer.gen.nullPtr\n"],["ref-def","sublibrary","ammer.def.* types","ammer.def.Sublibrary"," ammer.def.Sublibrary\nSublibrary definition. See sublibrary definition for examples.\nType parameters\nparent:Lib — parent library .\nAllowed fields\nStatic methods\nStatic variables\nStatic constants\nApplicable metadata\n@:ammer.nativePrefix\n@:ammer.sub\n"],["ref-lib",null,"ammer.Lib",null,"ammer.Lib\nThe ammer.Lib type provides a number of methods for client interaction with ammer libraries. These methods are (by necessity) macro methods. As a result, their signatures displayed below are only approximations.\n"],["ref-lib","allocstruct","ammer.Lib","ammer.Lib.allocStruct method"," ammer.Lib.allocStruct(type:Class, ?initialValues:{ ... }):Struct\nAllocates a struct of the given type, optionally assigning the given initial values to its fields. The type must be annotated with the @:ammer.alloc metadata.\nArguments\ntype — The name (or full path) of the type to allocate.\ninitialValues — An object literal where the keys and values correspond to fields and their initial values, respectively.\n"],["ref-lib","createhaxeref","ammer.Lib","ammer.Lib.createHaxeRef method"," ammer.Lib.createHaxeRef(type:Class, value:T):ammer.ffi.Haxe\nCreates a reference to the given Haxe value. See Haxe types .\nArguments\ntype — The name (or full path) of the Haxe type. This is required to make sure there are no unexpected type mismatch problems e.g. when passing references to anonymous structures .\nvalue — The Haxe value to create a reference to.\n"],["ref-lib","freestruct","ammer.Lib","ammer.Lib.freeStruct method"," ammer.Lib.freeStruct(instance:Struct):Void\nDeallocates the given pointer. The type must be annotated with the @:ammer.alloc metadata.\nArguments\ninstance — The value to deallocate.\n"],["ref-lib","nullptrstruct","ammer.Lib","ammer.Lib.nullPtrStruct method"," ammer.Lib.nullPtrStruct(type:Class):Struct\nReturns a null pointer of the given type.\nArguments\ntype — The name (or full path) of the type.\n"],["ref-flags",null,"List of configuration flags",null,"List of configuration flags\nNote that the _ after lib. in all the names below should be replaced by the identifier of the library.\nammer.buildPath\nammer.debug\nammer.outputPath\nammer.lib._.defines\nammer.lib._.frameworks\nammer.lib._.headers.includes\nammer.lib._.includePaths\nammer.lib._.language\nammer.lib._.libraryPaths\nammer.lib._.linkNames\n"],["ref-flags","buildpath","List of configuration flags","ammer.buildPath"," ammer.buildPath:String\nPath used for intermediate build artefacts. These include the C glue code generated by ammer, as well as compiled binary objects, before they are packaged into dynamic libraries. See paths .\nCompile-time defines\n-D ammer.buildPath=(string) — sets the build path.\n"],["ref-flags","debug","List of configuration flags","ammer.debug"," ammer.debug:String\nSets the debug mode for ammer. The value is a comma-separated list of categories of debug messages to show. The available categories are:\nstage\nstage-ffi\nThe flag can be set to the string all to enable all of the above.\nCompile-time defines\n-D ammer.debug=(comma-separated list) — sets the debug mode.\n"],["ref-flags","outputpath","List of configuration flags","ammer.outputPath"," ammer.outputPath:String\nPath used for final build products. These are dynamic libraries compiled by ammer that would typically be deployed with the program using them. See paths .\nCompile-time defines\n-D ammer.outputPath=(string) — sets the output path.\n"],["ref-flags","lib.defines","List of configuration flags","ammer.lib._.defines"," ammer.lib._.defines:Array\nList of C preprocessor directives to set when compiling the library.\nCompile-time defines\n-D ammer.lib._.define=(string) — adds one entry to the list.\n-D ammer.lib._.defines=(comma-separated list) — adds multiple entries to the list.\nMetadata (on a library definition)\n@:ammer.lib.define(define:String) — adds one entry to the list.\n@:ammer.lib.defines(defines:Array) — adds multiple entries to the list.\n"],["ref-flags","lib.frameworks","List of configuration flags","ammer.lib._.frameworks"," ammer.lib._.frameworks:Array\nList of frameworks to use when compiling the library. Only has an effect on macOS.\nCompile-time defines\n-D ammer.lib._.framework=(string) — adds one entry to the list.\n-D ammer.lib._.frameworks=(comma-separated list) — adds multiple entries to the list.\nMetadata (on a library definition)\n@:ammer.lib.framework(framework:String) — adds one entry to the list.\n@:ammer.lib.frameworks(frameworks:Array) — adds multiple entries to the list.\n"],["ref-flags","lib.headers","List of configuration flags","ammer.lib._.headers.includes"," ammer.lib._.headers.includes:Array\nList of headers to include when compiling the library. There are four different include styles:\nIncludeLocal — #include \"header.h\"\nIncludeGlobal — #include \nImportLocal — #import \"header.h\"\nImportGlobal — #import \nCompile-time defines\n-D ammer.lib._.headers=(comma-separated list) — adds multiple entries to the list, as IncludeLocals.\n-D ammer.lib._.headers.includeLocal=(string) — adds one entry to the list, as IncludeLocal.\n-D ammer.lib._.headers.includeGlobal=(string) — adds one entry to the list, as IncludeGlobal.\n-D ammer.lib._.headers.importLocal=(string) — adds one entry to the list, as ImportLocal.\n-D ammer.lib._.headers.importGlobal=(string) — adds one entry to the list, as ImportGlobal.\nMetadata (on a library definition)\n@:ammer.lib.headers.include(header:String) — adds one entry to the list, as IncludeLocal.\n@:ammer.lib.headers.import(header:String) — adds one entry to the list, as ImportLocal.\n@:ammer.lib.headers.includeLocal(header:String) — adds one entry to the list, as IncludeLocal.\n@:ammer.lib.headers.includeGlobal(header:String) — adds one entry to the list, as IncludeGlobal.\n@:ammer.lib.headers.importLocal(header:String) — adds one entry to the list, as ImportLocal.\n@:ammer.lib.headers.importGlobal(header:String) — adds one entry to the list, as ImportGlobal.\n"],["ref-flags","lib.includepaths","List of configuration flags","ammer.lib._.includePaths"," ammer.lib._.includePaths:Array\nPaths to provide to the C compiler as \"include paths\", which are used when searching for header files.\nCompile-time defines\n-D ammer.lib._.includePaths=(comma-separated list) — adds multiple entries to the list.\nMetadata (on a library definition)\n@:ammer.lib.includePath(path:String) — adds one entry to the list.\n@:ammer.lib.includePaths(paths:Array) — adds multiple entries to the list.\n"],["ref-flags","lib.language","List of configuration flags","ammer.lib._.language"," ammer.lib._.language:LibraryLanguage\nSpecifies the language of the native library. This language is also used for generating the glue code. Possible values:\nC - C\nCpp - C++\nObjC - Objective-C\nObjCpp - Objective-C++\nCompile-time defines\n-D ammer.lib._.language=(string) — sets the language.\nMetadata (on a library definition)\n@:ammer.lib.language(language:LibraryLanguage) — sets the language.\n"],["ref-flags","lib.librarypaths","List of configuration flags","ammer.lib._.libraryPaths"," ammer.lib._.libraryPaths:Array\nPaths to provide to the C compiler (more accurately, the linker) as \"library paths\", which are used when searching for library files ( .dll, .dylib, .so files).\nCompile-time defines\n-D ammer.lib._.libraryPaths=(comma-separated list) — adds multiple entries to the list.\nMetadata (on a library definition)\n@:ammer.lib.libraryPath(path:String) — adds one entry to the list.\n@:ammer.lib.libraryPaths(paths:Array) — adds multiple entries to the list.\n"],["ref-flags","lib.linknames","List of configuration flags","ammer.lib._.linkNames"," ammer.lib._.linkNames:Array\nNames of libraries to link against when compiling this native library. Should not include prefixes such as -l or lib.\nCompile-time defines\n-D ammer.lib._.linkNames=(comma-separated list) — adds multiple entries to the list.\nMetadata (on a library definition)\n@:ammer.lib.linkName(path:String) — adds one entry to the list.\n@:ammer.lib.linkNames(paths:Array) — adds multiple entries to the list.\n"],["ref-annot",null,"List of annotations",null,"List of annotations\nMetadata which do not correspond to a configuration flag are listed here.\n@:ammer.alloc\n@:ammer.c.cast\n@:ammer.c.macroCall\n@:ammer.c.prereturn\n@:ammer.c.return\n@:ammer.derive\n@:ammer.gen.alloc\n@:ammer.gen.free\n@:ammer.gen.nullPtr\n@:ammer.haxe\n@:ammer.native\n@:ammer.nativePrefix\n@:ammer.ret.derive\n@:ammer.skip\n@:ammer.sub\n"],["ref-annot","alloc","List of annotations","@:ammer.alloc"," @:ammer.alloc\nAllows allocation and deallocation of the annotated struct type using ammer.Lib.allocStruct and ammer.Lib.freeStruct, respectively. See allocation and deallocation .\n"],["ref-annot","c.cast","List of annotations","@:ammer.c.cast"," @:ammer.c.cast(type:String)\nMarks that the annotated argument should be cast to the given C type before being passed to the native call.\n"],["ref-annot","c.macrocall","List of annotations","@:ammer.c.macroCall"," @:ammer.c.macroCall\n(Alias: @:ammer.macroCall)\nMarks the annotated function as a macro call. See macro calls .\n"],["ref-annot","c.prereturn","List of annotations","@:ammer.c.prereturn"," @:ammer.c.prereturn(code:String)\nAdds the given C code into the native function, before the return expression. The arguments to the native call are available in the _arg0, ..., _argN local variables. See customising the C code .\n"],["ref-annot","c.return","List of annotations","@:ammer.c.return"," @:ammer.c.return(code:String)\nUses the given C expression instead of the return expression. The arguments to the native call are available in the _arg0, ..., _argN local variables. The string %CALL%, if used in code, will be replaced with the original return expression. See customising the C code .\n"],["ref-annot","derive","List of annotations","@:ammer.derive"," @:ammer.derive(e:Expr)\n"],["ref-annot","gen.alloc","List of annotations","@:ammer.gen.alloc"," @:ammer.gen.alloc(name:String)\nSpecifies the name for the generated static allocation function. See allocation and deallocation .\n"],["ref-annot","gen.free","List of annotations","@:ammer.gen.free"," @:ammer.gen.free(name:String)\nSpecifies the name for the generated instance deallocation function. See allocation and deallocation .\n"],["ref-annot","gen.nullptr","List of annotations","@:ammer.gen.nullPtr"," @:ammer.gen.nullPtr(name:String)\nSpecifies the name for the generated static null pointer function. See allocation and deallocation .\n"],["ref-annot","haxe","List of annotations","@:ammer.haxe"," @:ammer.haxe\nAllows the annotated function to have a Haxe body, skipping ammer processing. See pure Haxe functions .\n"],["ref-annot","native","List of annotations","@:ammer.native"," @:ammer.native(name:String)\nSpecifies the native name of the annotated function or field.\n"],["ref-annot","nativeprefix","List of annotations","@:ammer.nativePrefix"," @:ammer.nativePrefix(prefix:String)\nSpecifies the prefix for native names. The native name will be derived as \"prefix\" + \"the field name\", unless overridden on the field itself with @:ammer.native.\n"],["ref-annot","ret.derive","List of annotations","@:ammer.ret.derive"," @:ammer.ret.derive(e:Expr, ct:Type)\n"],["ref-annot","skip","List of annotations","@:ammer.skip"," @:ammer.skip\nMarks the given function argument to be skipped for the underlying native call.\n"],["ref-annot","sub","List of annotations","@:ammer.sub"," @:ammer.sub(sub:Type)\nMarks the given type sub as a \"subdefinition\" of the annotated library. See linking subdefinitions .\n"],["amlib",null,"amlib",null,"amlib\nTODO:\nstandard layout of amlib\nbakery defines ammer.bake\nammer.bake.mainType\nammer.bake.output\nammer.bake.rootToBin\nammer.bake.fileSource.*.name\nammer.bake.fileSource.*.downloadFrom\nammer.bake.fileSource.*.description\nammer.bake.fileSource.*.os\nammer.bake.fileSource.*.architectures\nammer.bake.fileSource.*.minVersion\nammer.bake.fileSource.*.maxVersion\n\nCI, GH action templates\nexamples of amlibs\n"],["advanced",null,"Advanced topics",null,"Advanced topics\n"],["advanced-cycles",null,"Type cycles",null,"Type cycles\nIn linking subdefinitions , it is recommended to link any library to all of its subdefinitions using the @:ammer.sub metadata. Why is this necessary?\nConsider the following types:\n// in file Foobar.hx\n@:ammer.sub((_ : FoobarStruct))\n@:ammer.sub((_ : FoobarSub))\nclass Foobar extends ammer.def.Library<\"foobar\"> {\n public static function some_function():FoobarStruct;\n}\n\n// in file FoobarStruct.hx\nclass FoobarStruct extends ammer.def.Struct<\"foobar_t\", Foobar> {\n // ...\n}\n\n// in file FoobarSub.hx\nclass FoobarSub extends ammer.def.Sublibrary {\n public static function another_function():Void;\n}\nBetween Foobar and FoobarSub, there is a two-way link:\n@:ammer.sub((_ : FoobarSub)) — Links the library to the subdefinition.\n... extends ammer.def.Sublibrary — Links the subdefinition to the library.\nIf the @:ammer.sub((_ : FoobarSub)) annotation was omitted, then the following client code could cause a compilation failure:\nFoobar.some_function();\nFoobarSub.another_function();\nThis is because Haxe performs typing on demand: the Foobar module (in the file Foobar.hx) is not discovered and typed until the first time it is needed. This can happen if a type (and its static method) declared in that module is used, as in the first line.\nHowever, Foobar is not a regular Haxe type: it is an ammer-annotated library definition. When an ammer library is typed, the following steps take place (simplified):\nA library context is established, containing the library configuration etc.\nAll fields of the library are eagerly typed. This may trigger transitive typing. In the example above, this leads Haxe to discover the FoobarStruct type, because it is used as the return type of one of the methods of Foobar.\nThe library is finalised by writing the required glue code into a file, which will later be compiled by a C compiler.\nWithout the @:ammer.sub((_ : FoobarSub)) annotation on Foobar, the first line of the client only causes the Haxe compiler to discover Foobar and FoobarStruct. When typing the second line (the call to FoobarSub.another_function), FoobarSub is discovered, but it cannot be added to Foobar anymore: the library was finalised and the glue code was already generated.\nThe safe recommendation is therefore to always use @:ammer.sub, even when other fields would cause the Haxe compiler to discover the subdefinitions.\n"],["core",null,"ammer-core",null,"ammer-core\nammer-core is a macro library that forms the foundation of ammer. Its main function is to allow each ammer target to be compiled and linked to C functions. To achieve this:\nFor each ammer target: It generates code that contains the C functions, along with any glue code required by the target's FFI mechanism.\nIn each function, it marshals data from the target's native representation to its C counterparts.\nIt defines a sequence of build steps that compiles the generated glue code, including any headers and dynamic libraries required by the target's FFI mechanism.\n\nFor each build system: It executes the sequence of build steps by invoking the concrete compiler/linker with appropriate arguments.\n\nThe API of ammer-core is quite low-level and stays quite close to the C counterparts. Notably, ammer-core does not map Haxe classes and types to native libraries, it does not assume that there is a single dynamic library being defined, and it does not process metadata or defines: these are all handled by ammer.\n"],["core-api",null,"Interface",null,"Interface\nThe main points of interaction with ammer-core are:\nammer.core.Platform (and concrete implementations in ammer.core.plat.*),\nammer.core.Library,\nammer.core.Marshal, and\nammer.core.Builder (and concrete implementations in ammer.core.build.*).\n"],["core-api","platform","Interface","`Platform`"," Platform\nA Platform represents one of ammer/ ammer-core targets. It can be constructed by calling ammer.core.Platform.createCurrentPlatform, or by directly calling a constructor of one of the ammer.core.plat.* types. The constructor takes a platform configuration, which is a class that contains at least the fields defined in ammer.core.plat.BaseConfig, but may contain more (required) fields: see ammer.core.plat.(Platform).(Platform)Config.\nPlatforms are used to create libraries with the createLibrary method. Once a library is finished (all its types and functions are declared), it is given to the platform with addLibrary. Finally, the finalise method returns a build program to be used by the builder .\n"],["core-api","library","Interface","`Library`"," Library\nA Library represents a set of types and functions that will be compiled as one unit into a dynamic library ( .dll, .dylib, .so).\nAs mentioned above, a Library is obtained from a platform using createLibrary: this function takes a library configuration object. This is a class that contains at least the fields defined in ammer.core.LibraryConfig, but platforms may add more fields, see ammer.core.plat.(Platform).(Platform)LibraryConfig.\nLibraries contain a reference to a marshal object, and can have code added to them using these functions:\naddInclude, addCode, addHeaderCode — add code directly.\naddFunction — adds a function with the given signature and body which can be called from Haxe using the returned expression.\naddCallback, addStaticCallback — add functions forwarding calls to Haxe closures (or static methods, respectively) that can be called from native code using the returned name. The code provided to these functions will often make use of the closureCall and staticCall functions, which performs the actual call to a Haxe closure, given its reference.\n"],["core-api","marshal","Interface","`Marshal`"," Marshal\nMarshal is the class that defines how values are marshalled (passed through) between Haxe and C. It has methods for each kind of type that ammer-core understands. These methods return instances of TypeMarshal, which can then be passed to functions such as addFunction to define signatures of functions.\n"],["core-api","builder","Interface","`Builder`"," Builder\nA Builder represents a build system, such as GCC or MSVC, that is used to execute the build steps returned by finalising a platform, with the build function.\n"],["core-new-platform",null,"Implementing new platforms",null,"Implementing new platforms\nAbout type representation\nInstances of TypeMarshal (obtained from a Marshal instance ) define how any given type is to be passed between Haxe and C. This marshalling is performed in up to three steps in C code (depending on the concrete platform and type), named L1 (closest to Haxe and the concrete Haxe target), L2, and L3 (unified C representation).\nhaxeType — the ComplexType used for this type in calls from Haxe.\nmangled — a short representation of the type, used in identifiers and mangled function signatures.\nl1Type, l2Type, l3Type — the C type at each step.\nl1l2, l2l3, l3l2, l2l1 — functions which output the C code that transforms the value from one level to another. For example, l1l2 is given as first argument an expression representing the L1 representation, as second argument an identifier to which the L2 representation will be written, and returns the code that performs e.g. (l2) = transform((l1));. The generated code may span multiple lines and may require multiple method calls interacting with the current platform's FFI mechanism.\nImplementing the platform file\nTo create a new Platform, it is best to follow examples of existing platforms, whose implementations are in the ammer.core.plat package. There is also a None platform which performs no-ops or raises exceptions for all of its operations; it can also serve as a good template file for new platform implementations.\nTypes such as ammer.core.Platform and ammer.core.PlatformId should also be adapted to make ammer-core aware of the new platform.\nWhen developing the actual implementation, a rough guideline is as follow:\nStart with outputting any C glue code.\nImplement addNamedFunction (with dummy arguments at first).\nImplement types in Marshal, enabling tests one at a time. The simplest test is probably TestBools, requiring only the Bool type marshalling to work.\n\nImplement the finalise steps to get a dynamic library that actually compiles and links against the target's FFI mechanism.\nEnable and pass the other tests: integers, TestIntegers.hx\nfloats, TestFloats.hx\nopaques, part of TestStructs.hx\nstructs, rest of TestStructs.hx\nbytes, TestBytes.hx\narrays, Haxe values, callbacks ...\n\nPlatform configuration, polish.\n"]] \ No newline at end of file diff --git a/target-cs.html b/target-cs.html new file mode 100644 index 0000000..7072dcc --- /dev/null +++ b/target-cs.html @@ -0,0 +1,40 @@ + + C# – ammer manual + + + + + +

ammer

+ +

C#

Target summary

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersFrom Haxe to native only
Shared vectorsFrom Haxe to native only
+

Configuration flags

(no additional flags)

+
+ « Previous: C++ + Next: Eval » + + \ No newline at end of file diff --git a/target-eval.html b/target-eval.html index 854edee..7efd781 100644 --- a/target-eval.html +++ b/target-eval.html @@ -2,18 +2,39 @@ Eval – ammer manual + +

ammer

- -

Eval

Native extensions for eval are supported via the plugin system in Haxe. Dynamic libraries can be linked to an OCaml dynamic library (.cmxs or .cmo), which can be loaded at runtime by Haxe. However, the plugin must be compiled with the exact same OCaml version and configuration as Haxe itself. Therefore Eval is only supported with Haxe set up to compile from its sources. The ammer.eval.haxeDir define must be set to point to the haxe repository directory. ammer.eval.bytecode may be defined to indicate that Haxe is built using the bytecode compiler, which means the native library must also be compiled in this mode.

-

During compilation with ammer, the .cmxs (or .cmo) file for a native library needs to be (re-)compiled whenever the native library or the Haxe library definition changes.

-

This process is facilitated by creating a Makefile and FFI-defining C files in the directory defined by ammer.eval.build. The compiled cmxs files are then placed into the directory defined by ammer.eval.output. Both directories default to the current working directory when not specified.

+ +

Eval

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersNo
Shared vectorsNo
+

Configuration flags

(no additional flags)

- « Previous: C++ + « Previous: C# Next: HashLink » \ No newline at end of file diff --git a/target-feature-parity.html b/target-feature-parity.html new file mode 100644 index 0000000..63d0781 --- /dev/null +++ b/target-feature-parity.html @@ -0,0 +1,36 @@ + + Feature parity – ammer manual + + + + + +

ammer

+ +

Feature parity

Shared buffers

Since each ammer target has a different runtime with different internal representations of core types such as haxe.io.Bytes, some targets do not support directly sharing memory between Haxe code and native code.

+

In the target summaries in the remaining sections, "Shared buffers" is one of the following:

+
    +
  • Yes - haxe.io.Bytes can be passed directly (without copying) to the native library as a byte pointer and vice versa.
  • +
  • From Haxe to native only - haxe.io.Bytes can be passed directly (without copying) to the native library as a byte pointer but a native byte pointer cannot be used as a haxe.io.Bytes value.
  • +
  • No - haxe.io.Bytes must always be copied to get a byte pointer.
  • +
+

Shared vectors

In the target summaries in the remaining sections, "Shared vectors" is one of the following:

+
    +
  • Yes - haxe.ds.Vector can be passed directly (without copying) to the native library as a pointer and vice versa.
  • +
  • From Haxe to native only - haxe.ds.Vector can be passed directly (without copying) to the native library as a pointer but a native pointer cannot be used as a haxe.ds.Vector value.
  • +
  • No - haxe.ds.Vector must always be copied to get a pointer.
  • +
+
+ « Previous: Target details + Next: C++ » + + \ No newline at end of file diff --git a/target-hashlink.html b/target-hashlink.html index 55c6bc0..505e8a9 100644 --- a/target-hashlink.html +++ b/target-hashlink.html @@ -2,26 +2,44 @@ HashLink – ammer manual + +

ammer

- -

HashLink

HashLink can use native libraries when given .hdll files containing the stubs, which take HashLink types and pass them onto the dynamically-loaded library. The .hdll files specify dynamic linkage and provide HashLink FFI, as understood by the HashLink interpreter/VM hl.

-

During compilation with ammer, the .hdll file for a native library needs to be (re-)compiled whenever the native library or the Haxe library definition changes.

-

This process is facilitated by creating a Makefile and FFI-defining C files in the directory defined by ammer.hl.build. The compiled hdll files are then placed into the directory defined by ammer.hl.output. Both directories are the same as the .hl output by default.

-
-D ammer.hl.build=where/to/place/the/stubs
--D ammer.hl.output=where/to/place/the/hdll/files
---hl where/to/place/the/output.hl
-

When running, the .hdll file must be present either in the current working directory, or in the library directory (e.g. /usr/local/lib). For distributing programs to end users, the former is preferred (since the .hdll files need not be installed).

-

ammer.hl.hlInclude, ammer.hl.hlLibrary

Optional

-

Compilation of HashLink .hdll files relies on the hl.h header and the libhl library (the libhl.dylib or libhl.lib file in particular). These defines should be used if the HashLink headers are not present in the default include path.

-

When using HashLink built from source, ammer.hl.hlInclude should point to the src directory of the HashLink repository clone, and ammer.hl.hlLibrary to the directory containing the binaries produced during HashLink compilation.

-

When using a binary release of HashLink, both paths should point to the include directory distributed along with the executable.

-
+ +

HashLink

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersYes
Shared vectorsYes
+

Configuration flags

+
+

ammer.hl.includePaths:Array<String>


+

ammer.hl.libraryPaths:Array<String>

« Previous: Eval - Next: Lua » + Next: Java » \ No newline at end of file diff --git a/target-hxcpp.html b/target-hxcpp.html index 40674a5..ab7b771 100644 --- a/target-hxcpp.html +++ b/target-hxcpp.html @@ -2,21 +2,43 @@ C++ – ammer manual + +

ammer

- -

C++

hxcpp includes a native compilation stage, so external libraries can be dynamically linked directly, without relying on FFI methods.

-

If the Haxe class has the same name as the main header file of the library, a problem might occur - hxcpp also generates header files that carry the name of the class they represent. To circumvent this problem, create a copy with a different filename, then use ammer.lib.<name>.headers:

-
$ cp foobar.h tmp.foobar.h
-
-D ammer.lib.foobar.headers=tmp.foobar.h
- - + +

C++

Target summary

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersYes
Shared vectorsYes
+

Configuration flags

+
+

Defaults to true. Note that dynamic linking on C++ is planned, but not yet implemented.

- « Previous: Target details - Next: Eval » + « Previous: Feature parity + Next: C# » \ No newline at end of file diff --git a/target-java.html b/target-java.html new file mode 100644 index 0000000..d3cfc39 --- /dev/null +++ b/target-java.html @@ -0,0 +1,45 @@ + + Java – ammer manual + + + + + +

ammer

+ +

Java

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersFrom Haxe to native only
Shared vectorsFrom Haxe to native only
+

Configuration flags

+
+

ammer.java.includePaths:Array<String>


+

ammer.java.libraryPaths:Array<String>

+ « Previous: HashLink + Next: Lua » + + \ No newline at end of file diff --git a/target-lua.html b/target-lua.html index 7c32eac..a67fb5e 100644 --- a/target-lua.html +++ b/target-lua.html @@ -2,18 +2,44 @@ Lua – ammer manual + +

ammer

- -

Lua

Native libraries on Lua are loaded using the Lua/C API, which works on both the standard Lua interpreter and LuaJIT. A dynamic library containing stubs is generated by ammer and loaded at runtime using package.loadlib.

-

ammer.lua.luaInclude, ammer.lua.luaLibrary

Optional

-

Compilation of the dynamic library containing Lua stubs relies on Lua headers and the liblua library. These defines should be used if the Lua headers or library respectively are not present in the default paths.

-
- « Previous: HashLink - Next: Native library development » + +

Lua

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersNo
Shared vectorsNo
+

Configuration flags

+
+

ammer.lua.includePaths:Array<String>


+

ammer.lua.libraryPaths:Array<String>

+ « Previous: Java + Next: Neko » \ No newline at end of file diff --git a/target-neko.html b/target-neko.html new file mode 100644 index 0000000..28ee6ee --- /dev/null +++ b/target-neko.html @@ -0,0 +1,45 @@ + + Neko – ammer manual + + + + + +

ammer

+ +

Neko

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersFrom Haxe to native only
Shared vectorsNo
+

Configuration flags

+
+

ammer.neko.includePaths:Array<String>


+

ammer.neko.libraryPaths:Array<String>

+ « Previous: Lua + Next: Node.js » + + \ No newline at end of file diff --git a/target-nodejs.html b/target-nodejs.html new file mode 100644 index 0000000..d8432f9 --- /dev/null +++ b/target-nodejs.html @@ -0,0 +1,43 @@ + + Node.js – ammer manual + + + + + +

ammer

+ +

Node.js

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersYes
Shared vectorsNo
+

Configuration flags

+
+

ammer.js.nodeGypBinary:String

+ « Previous: Neko + Next: Python » + + \ No newline at end of file diff --git a/target-python.html b/target-python.html new file mode 100644 index 0000000..019ccef --- /dev/null +++ b/target-python.html @@ -0,0 +1,47 @@ + + Python – ammer manual + + + + + +

ammer

+ +

Python

+ + + + + + + + + + + + + + +
FeatureStatus
Shared buffersFrom Haxe to native only
Shared vectorsNo
+

Configuration flags

+
+

ammer.python.version:Int


+

ammer.python.includePaths:Array<String>


+

ammer.python.libraryPaths:Array<String>

+ « Previous: Node.js + Next: Reference » + + \ No newline at end of file diff --git a/target.html b/target.html index 2175205..92c900c 100644 --- a/target.html +++ b/target.html @@ -2,76 +2,38 @@ Target details – ammer manual + +

ammer

- -

Target details

Feature matrix

All features listed should eventually be available on all supported platforms.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FeatureC++EvalHashLinkLua
Functionsyesyesyesyes
C code injectionyesnoyesyes
Constantsyesnoyesyes
Library datatypesyesnoyesyes
Library variablesyesnoyesyes
Enumerationsyesnoyesyes
Callbacksyesnoyesno
+ +

Target details

ammer aims to support all Haxe sys targets, including Javascript compiled with hxnodejs, but excluding PHP.

+

Feature parity

Each ammer target supports the same set of features, unless otherwise noted.

+

Read on: Feature parity

+

Target-specific information

The rest of this chapter contains information on how each target should be used, its configuration flags, etc.

+

Read on:

+
« Previous: Library configuration - Next: C++ » + Next: Feature parity » \ No newline at end of file