github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/docs/concepts/stdlibs/gnopher-hole.md (about)

     1  ---
     2  id: gnopher-hole-stdlib
     3  ---
     4  
     5  # Gnopher Hole
     6  
     7  ## Native bindings
     8  
     9  Gno has support for "natively-defined" functions  exclusively within the standard
    10  libraries. These are functions which are _declared_ in Gno code, but only _defined_
    11  in Go. There are generally three reasons why a function should be natively
    12  defined:
    13  
    14  1. It relies on inspecting the Gno Virtual Machine itself, i.e. `std.AssertOriginCall`
    15     or `std.CurrentRealmPath`.
    16  2. It relies on `unsafe`, or other features which are not planned to be
    17     available in the GnoVM, i.e. `math.Float64frombits`.
    18  3. Its native Go performance significantly outperforms the Gno counterpart by
    19     several orders of magnitude, and it is used in crucial code or hot paths in
    20     many programs, i.e. `sha256.Sum256`.
    21  
    22  Native bindings are made to be a special feature which can be
    23  help overcome pure Gno limitations, but it is not a substitute for writing
    24  standard libraries in Gno.
    25  
    26  There are three components to a natively bound function in Gno:
    27  
    28  1. The Gno function declaration, which must be a top-level function with no body
    29     (and no brackets), i.e. `crypto/sha256/sha256.gno`.
    30  2. The Go function definition, which must be a top-level function with the same
    31     name and signature, i.e. `crypto/sha256/sha256.go`.
    32  3. When the two above are present and valid, the native binding can be created
    33     by executing the code generator: either by executing `go generate` from the
    34     `stdlibs` directory, or run `make generate` from the `gnovm` directory.
    35     This generates the `native.go` file available in the `stdlibs` directory,
    36     which provides the binding itself to then be used by the GnoVM.
    37  
    38  The code generator in question is available in the `misc/genstd` directory.
    39  There are some quirks and features that must be kept in mind when writing native
    40  bindings, which are the following:
    41  
    42  - Unexported functions (i.e. `func sum256(b []byte)`) must have their
    43    Go counterpart prefixed with `X_` in order to make the functions exported (i.e.
    44    `func X_sum256(b []byte)`).
    45  - The Go function declaration may specify as the first argument
    46    `m *gno.Machine`, where `gno` is an import for
    47    `github.com/gnolang/gno/gnovm/pkg/gnolang`. This gives the function access to
    48    the Virtual Machine state, and is used by functions like `std.AssertOriginCall()`.
    49  - The Go function may change the type of any parameter or result to
    50    `gno.TypedValue`, where `gno` is an import for the above import path. This
    51    means that the `native.go` generated code will not attempt to automatically
    52    convert the Gno value into the Go value, and can be useful for unsupported
    53    conversions like interface values.
    54  - A small set of named types are "linked" between their Gno version and Go
    55    counterpart. For instance, `std.Address` in Gno is
    56    `(".../tm2/pkg/crypto").Bech32Address` in Go. A list of these can be found in
    57    `misc/genstd/mapping.go`.
    58  - Not all type literals are currently supported when converting from their Gno
    59    version to their Go counterpart, i.e. `struct` and `map` literals. If you intend to use these,
    60    modify the code generator to support them.
    61  - The code generator does not inspect any imported packages from the Go native code
    62    to determine the default package identifier (i.e. the `package` clause).
    63    For example, if a package is in `foo/bar`, but declares `package xyz`, when importing
    64    foo/bar the generator will assume the name to be `bar` instead of `xyz`.
    65    You can add an identifier to the import to fix this and use the identifier
    66    you want/need, such as `import gno "github.com/gnolang/gno/gnovm/pkg/gnolang"`.
    67  
    68  ## Adding new standard libraries
    69  
    70  New standard libraries may be added by simply creating a new directory (whose
    71  path relative to the `stdlibs` directory will be the import path used in Gno
    72  programs). Following that, the suggested approach for adding a Go standard
    73  library is to copy the original files from the Go source tree, and renaming their
    74  extensions from `.go` to `.gno`.
    75  
    76  :::note
    77  As a small aid, this bash one-liner can be useful to convert all the file
    78  extensions:
    79  ```sh
    80  for i in *.go; do mv $i "$(echo $i | sed 's/\.go$/.gno/')"; done
    81  ```
    82  :::  
    83  
    84  Following that, the suggested approach is to iteratively try running `gno test .`,
    85  while fixing any errors that may come out of trying to test the package.
    86  
    87  Some things to keep in mind:
    88  
    89  - Gno doesn't support assembly functions and build tags. Some Go packages may
    90    contain assembly versions for different architecture and a `generic.go` file
    91    containing the architecture-independent version. The general approach is that
    92    of removing everything architecture/os-specific except for the `generic.go` file.
    93  - Gno doesn't support reflection at the time of writing, which means that for
    94    now many packages which rely heavily on reflection have to be delayed or
    95    reduced while we figure out the details on how to implement reflection.
    96    Aside from the `reflect` package itself, this also translates to very common
    97    packages still not available in Gno, such as `fmt` or `encoding/json`.
    98  - In the package documentation, specify the Go version from which the library
    99    was taken.
   100  - All changes from the Go standard libraries must be explicitly marked, possibly
   101    with `// XXX` comments as needed.
   102  
   103  If you intend to create a PR to add a new standard library, remember to update
   104  [Go<\>Gno compatibility](../../reference/go-gno-compatibility.md) accordingly.
   105  
   106