mapper

package module
v0.0.0-...-aef762d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2021 License: BSD-3-Clause Imports: 4 Imported by: 0

README

go-mapper

This package makes it easier to "pass" Go values into C code via cgo, and back out again, without violating the cgo pointer passing rules.

Our Mapper does this by associating an opaque Key with the Go object, and having the caller pass the key in place of the Go object. Later, in a Go callback for example, the Go object can be obtained using the Get method on the Mapper in exchange for the key.

You can create a Mapper object for each different category of mapping, or reuse the same one for all, with the caveats of mapping limits described below. A global mapper, G is provided for your convenience.

Internally, the mapper uses a RWLock-protected Go map to associate Keys with Go values. The following patterns are supported:

  1. You have a pointer already obtained from cgo, which is at least 2-bytes aligned. (Any pointer returned from malloc satisfies this property.)

    That pointer can be mapped to a Go value using the MapPtrPair method. The returned Key can then be used to obtain the mapped Go value using the Get method.

  2. You need to create a new mapping for a Go object, without having a pointer previously obtained from cgo. This might be the case with a C API that accepts an opaque "user defined" pointer (or "refCon" in Apple's APIs), but doesn't return its object until after the call. Such a user pointer might be passed to a callback that makes it way back to Go, where you then exchange the pointer for the mapped Go object.

    In this case, you can map a Go object to a unique Key that is returned from the MapValue method. To keep the implementation simple, the number of unique keys is limited to sizeof(uintptr)/2. When the limit is reached, the MapValue call panics. On a 64-bit system, it is unlikely that any long-running program will reach that limit.

    Under this pattern, you can "stretch" the map limit further on a 32-bit system by using multiple Mappers, each for different categories of object mappings, instead of the global map G.

Example

See example/main.go.

License

MIT, see the LICENSE.md file.

Documentation

Overview

Package mapper makes it easy to exchange Go values for a pointer that can be passed to C APIs, and then retrieve the original Go value in a Go callback.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Key

type Key struct {
	// contains filtered or unexported fields
}

Key is an opaque token used to map onto Go values.

func KeyFromPtr

func KeyFromPtr(ptr unsafe.Pointer) Key

KeyFromPtr converts a cgo pointer to a Key.

The key can be any unique pointer, but it is recommended that it be a value obtained from outside the view of the Go GC, in case the GC moves that memory around. Typically key is a malloc-based pointer obtained from cgo.

We require the key to be at least 2-bytes aligned: that is, the lower bit must be zero, which is a reasonable assumption for pointers returned via malloc.

func (Key) Handle

func (k Key) Handle() unsafe.Pointer

Handle returns an opaque "pointer" value that can be used to pass to cgo. The returned value is pointer-sized, but should never be de-referenced.

type Mapper

type Mapper struct {
	// contains filtered or unexported fields
}

Mapper maps between Key and Go values.

var G Mapper

G is the global mapper... for users who don't care about lock contention. For those that do, it is recommended to use a separate Mapper instance.

func (*Mapper) Clear

func (mapper *Mapper) Clear()

Clear all mappings.

func (*Mapper) Delete

func (mapper *Mapper) Delete(key Key)

Delete an existing mapping via the key.

func (*Mapper) Get

func (mapper *Mapper) Get(key Key) (goValue interface{})

Get retrieves the Go value from key.

func (*Mapper) GetPtr

func (mapper *Mapper) GetPtr(ptr unsafe.Pointer) (goValue interface{})

GetPtr calls Get after first converting ptr to a Key.

func (*Mapper) MapPair

func (mapper *Mapper) MapPair(key Key, goValue interface{})

MapPair creates a mapping between the provided Key and Go value.

func (*Mapper) MapPtrPair

func (mapper *Mapper) MapPtrPair(ptr unsafe.Pointer, goValue interface{}) Key

MapPtrPair is like MapPair, but maps from a cgo pointer, and returns the associated Key. This method is a convenience wrapper around KeyFromPtr and MapPair.

func (*Mapper) MapValue

func (mapper *Mapper) MapValue(goValue interface{}) Key

MapValue maps a new Key to the given Go value, and returns the Key.

The key here is a sizeof(pointer)/2 atomic, that is simply incremented by two on each call. On a 64-bit platform, this key-space is so large that is will unlikely ever run out during the lifetime of a program... but if it does, we panic. To avoid running out of space on a 32-bit platform (where 2,147,483,648 mappings are possible), use MapPtrPair instead.

Directories

Path Synopsis
internal
testing
Package testing allows us to use cgo in Go tests.
Package testing allows us to use cgo in Go tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL