@@ -24,29 +24,75 @@ import (
24
24
"fmt"
25
25
"math"
26
26
"reflect"
27
+ "sync"
27
28
"unsafe"
28
29
)
29
30
30
31
//export callbackTrampoline
31
32
func callbackTrampoline (ctx * C.sqlite3_context , argc int , argv * * C.sqlite3_value ) {
32
33
args := (* [(math .MaxInt32 - 1 ) / unsafe .Sizeof ((* C .sqlite3_value )(nil ))]* C.sqlite3_value )(unsafe .Pointer (argv ))[:argc :argc ]
33
- fi := ( * functionInfo )( unsafe . Pointer ( C .sqlite3_user_data (ctx )))
34
+ fi := lookupHandle ( uintptr ( C .sqlite3_user_data (ctx ))).( * functionInfo )
34
35
fi .Call (ctx , args )
35
36
}
36
37
37
38
//export stepTrampoline
38
39
func stepTrampoline (ctx * C.sqlite3_context , argc int , argv * * C.sqlite3_value ) {
39
40
args := (* [(math .MaxInt32 - 1 ) / unsafe .Sizeof ((* C .sqlite3_value )(nil ))]* C.sqlite3_value )(unsafe .Pointer (argv ))[:argc :argc ]
40
- ai := ( * aggInfo )( unsafe . Pointer ( C .sqlite3_user_data (ctx )))
41
+ ai := lookupHandle ( uintptr ( C .sqlite3_user_data (ctx ))).( * aggInfo )
41
42
ai .Step (ctx , args )
42
43
}
43
44
44
45
//export doneTrampoline
45
46
func doneTrampoline (ctx * C.sqlite3_context ) {
46
- ai := (* aggInfo )(unsafe .Pointer (C .sqlite3_user_data (ctx )))
47
+ handle := uintptr (C .sqlite3_user_data (ctx ))
48
+ ai := lookupHandle (handle ).(* aggInfo )
47
49
ai .Done (ctx )
48
50
}
49
51
52
+ // Use handles to avoid passing Go pointers to C.
53
+
54
+ type handleVal struct {
55
+ db * SQLiteConn
56
+ val interface {}
57
+ }
58
+
59
+ var handleLock sync.Mutex
60
+ var handleVals = make (map [uintptr ]handleVal )
61
+ var handleIndex uintptr = 100
62
+
63
+ func newHandle (db * SQLiteConn , v interface {}) uintptr {
64
+ handleLock .Lock ()
65
+ defer handleLock .Unlock ()
66
+ i := handleIndex
67
+ handleIndex ++
68
+ handleVals [i ] = handleVal {db , v }
69
+ return i
70
+ }
71
+
72
+ func lookupHandle (handle uintptr ) interface {} {
73
+ handleLock .Lock ()
74
+ defer handleLock .Unlock ()
75
+ r , ok := handleVals [handle ]
76
+ if ! ok {
77
+ if handle >= 100 && handle < handleIndex {
78
+ panic ("deleted handle" )
79
+ } else {
80
+ panic ("invalid handle" )
81
+ }
82
+ }
83
+ return r .val
84
+ }
85
+
86
+ func deleteHandles (db * SQLiteConn ) {
87
+ handleLock .Lock ()
88
+ defer handleLock .Unlock ()
89
+ for handle , val := range handleVals {
90
+ if val .db == db {
91
+ delete (handleVals , handle )
92
+ }
93
+ }
94
+ }
95
+
50
96
// This is only here so that tests can refer to it.
51
97
type callbackArgRaw C.sqlite3_value
52
98
0 commit comments