-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpointers.go
More file actions
53 lines (46 loc) · 1.46 KB
/
pointers.go
File metadata and controls
53 lines (46 loc) · 1.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package sqlite
import (
"reflect"
"runtime/cgo"
"sync"
)
// #include <stdint.h>
// extern char * go_strcpy(_GoString_ st);
import "C"
// Marker type for values that should be passed as pointer.
// Most users will prefer [AsPointer].
type PointerValue cgo.Handle
// static (compile-time) name for a pointer
//
// the C documentation is pretty clear about the need to have static strings as
// identifiers for the type of the pointer passed in functions.
// Go does offer better runtime introspection, so we use this to remove the noise.
func namefor(tt reflect.Type) *C.char {
gn := tt.PkgPath() + "." + tt.Name()
mxTypeNames.Lock()
nn, ok := typenames[gn]
if !ok {
nn = C.go_strcpy(gn)
typenames[gn] = nn
}
mxTypeNames.Unlock()
return nn
}
var typenames = make(map[string]*C.char)
var mxTypeNames sync.Mutex
// AsPointer is used to pass the value using the SQLite pointer passing [interface].
// This interface is only useful for reading the value in virtual functions.
// The “pointer type” parameter will be derived from the underlying data type name.
//
// [interface]: https://sqlite.org/bindptr.html
func (ctn *Conn) AsPointer(v any) PointerValue {
if reflect.TypeOf(v).Kind() != reflect.Pointer && reflect.TypeOf(v).Elem().Kind() != reflect.Struct {
panic("AsPointer must be given a pointer to a struct")
}
ctn.pointers.Pin(v)
return PointerValue(cgo.NewHandle(v))
}
//export cleanupGoHandle
func cleanupGoHandle(hdl C.uintptr_t) {
cgo.Handle(hdl).Delete()
}