Documentation ¶
Overview ¶
An example of wrapping a C library in Go. This is the GNU multiprecision library gmp's integer type mpz_t wrapped to look like the Go package big's integer type Int.
This is a syntactically valid Go program—it can be parsed with the Go parser and processed by godoc—but it is not compiled directly by 6g. Instead, a separate tool, cgo, processes it to produce three output files. The first two, 6g.go and 6c.c, are a Go source file for 6g and a C source file for 6c; both compile as part of the named package (gmp, in this example). The third, gcc.c, is a C source file for gcc; it compiles into a shared object (.so) that is dynamically linked into any 6.out that imports the first two files.
The stanza
// #include <gmp.h> import "C"
is a signal to cgo. The doc comment on the import of "C" provides additional context for the C file. Here it is just a single #include but it could contain arbitrary C definitions to be imported and used.
Cgo recognizes any use of a qualified identifier C.xxx and uses gcc to find the definition of xxx. If xxx is a type, cgo replaces C.xxx with a Go translation. C arithmetic types translate to precisely-sized Go arithmetic types. A C struct translates to a Go struct, field by field; unrepresentable fields are replaced with opaque byte arrays. A C union translates into a struct containing the first union member and perhaps additional padding. C arrays become Go arrays. C pointers become Go pointers. C function pointers become Go's uintptr. C void pointers become Go's unsafe.Pointer.
For example, mpz_t is defined in <gmp.h> as:
typedef unsigned long int mp_limb_t; typedef struct { int _mp_alloc; int _mp_size; mp_limb_t *_mp_d; } __mpz_struct; typedef __mpz_struct mpz_t[1];
Cgo generates:
type _C_int int32 type _C_mp_limb_t uint64 type _C___mpz_struct struct { _mp_alloc _C_int; _mp_size _C_int; _mp_d *_C_mp_limb_t; } type _C_mpz_t [1]_C___mpz_struct
and then replaces each occurrence of a type C.xxx with _C_xxx.
If xxx is data, cgo arranges for C.xxx to refer to the C variable, with the type translated as described above. To do this, cgo must introduce a Go variable that points at the C variable (the linker can be told to initialize this pointer). For example, if the gmp library provided
mpz_t zero;
then cgo would rewrite a reference to C.zero by introducing
var _C_zero *C.mpz_t
and then replacing all instances of C.zero with (*_C_zero).
Cgo's most interesting translation is for functions. If xxx is a C function, then cgo rewrites C.xxx into a new function _C_xxx that calls the C xxx in a standard pthread. The new function translates its arguments, calls xxx, and translates the return value.
Translation of parameters and the return value follows the type translation above except that arrays passed as parameters translate explicitly in Go to pointers to arrays, as they do (implicitly) in C.
Garbage collection is the big problem. It is fine for the Go world to have pointers into the C world and to free those pointers when they are no longer needed. To help, the Go code can define Go objects holding the C pointers and use runtime.SetFinalizer on those Go objects.
It is much more difficult for the C world to have pointers into the Go world, because the Go garbage collector is unaware of the memory allocated by C. The most important consideration is not to constrain future implementations, so the rule is that Go code can hand a Go pointer to C code but must separately arrange for Go to hang on to a reference to the pointer until C is done with it.
Index ¶
- func CmpInt(x, y *Int) int
- func DivModInt(q, r, x, y *Int)
- func GcdInt(d, x, y, a, b *Int)
- type Int
- func (z *Int) Abs(x *Int) *Int
- func (z *Int) Add(x, y *Int) *Int
- func (z *Int) Bytes() []byte
- func (z *Int) Div(x, y *Int) *Int
- func (z *Int) Exp(x, y, m *Int) *Int
- func (z *Int) Int64() int64
- func (z *Int) Len() int
- func (z *Int) Lsh(x *Int, s uint) *Int
- func (z *Int) Mod(x, y *Int) *Int
- func (z *Int) Mul(x, y *Int) *Int
- func (z *Int) Neg(x *Int) *Int
- func (z *Int) ProbablyPrime(n int) bool
- func (z *Int) Rsh(x *Int, s uint) *Int
- func (z *Int) Set(x *Int) *Int
- func (z *Int) SetBytes(b []byte) *Int
- func (z *Int) SetInt64(x int64) *Int
- func (z *Int) SetString(s string, base int) error
- func (z *Int) String() string
- func (z *Int) Sub(x, y *Int) *Int
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Int ¶
type Int struct {
// contains filtered or unexported fields
}
An Int represents a signed multi-precision integer. The zero value for an Int represents the value 0.
func (*Int) Mod ¶
Mod sets z = x % y and returns z. Like the result of the Go % operator, z has the same sign as x.
func (*Int) ProbablyPrime ¶
ProbablyPrime performs n Miller-Rabin tests to check whether z is prime. If it returns true, z is prime with probability 1 - 1/4^n. If it returns false, z is not prime.
func (*Int) SetBytes ¶
SetBytes interprets b as the bytes of a big-endian integer and sets z to that value.