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