@@ -18,11 +18,12 @@ import (
18
18
var libInit sync.Once
19
19
20
20
var (
21
+ client * NativeServiceClient
21
22
lib uintptr
22
23
serviceNew func (uint64 ) uintptr
23
24
serviceDelete func (uintptr )
24
25
serviceCall func (uintptr , string , string , uint , * uint ) uintptr
25
- freeString func (uintptr )
26
+ free func (uintptr , uint )
26
27
)
27
28
28
29
type validator interface {
@@ -33,13 +34,20 @@ type NativeServiceClient struct {
33
34
svc uintptr
34
35
}
35
36
36
- func initLib ( ) {
37
+ func initClient ( pluginAgent uint64 ) {
37
38
libInit .Do (func () {
38
39
lib , _ = loadServiceNativeLib ()
39
40
purego .RegisterLibFunc (& serviceNew , lib , "kclvm_service_new" )
40
41
purego .RegisterLibFunc (& serviceDelete , lib , "kclvm_service_delete" )
41
42
purego .RegisterLibFunc (& serviceCall , lib , "kclvm_service_call_with_length" )
42
- purego .RegisterLibFunc (& freeString , lib , "kclvm_service_free_string" )
43
+ purego .RegisterLibFunc (& free , lib , "kcl_free" )
44
+ client = new (NativeServiceClient )
45
+ client .svc = serviceNew (pluginAgent )
46
+ runtime .SetFinalizer (client , func (x * NativeServiceClient ) {
47
+ if x != nil {
48
+ x .Close ()
49
+ }
50
+ })
43
51
})
44
52
}
45
53
@@ -48,16 +56,13 @@ func NewNativeServiceClient() api.ServiceClient {
48
56
}
49
57
50
58
func NewNativeServiceClientWithPluginAgent (pluginAgent uint64 ) * NativeServiceClient {
51
- initLib ()
52
- c := new (NativeServiceClient )
53
- c .svc = serviceNew (pluginAgent )
54
- runtime .SetFinalizer (c , func (x * NativeServiceClient ) {
55
- if x .svc != 0 {
56
- serviceDelete (x .svc )
57
- }
58
- closeLibrary (lib )
59
- })
60
- return c
59
+ initClient (pluginAgent )
60
+ return client
61
+ }
62
+
63
+ func (x * NativeServiceClient ) Close () {
64
+ serviceDelete (x .svc )
65
+ closeLibrary (lib )
61
66
}
62
67
63
68
func cApiCall [I interface {
@@ -87,7 +92,10 @@ func cApiCall[I interface {
87
92
var cOutSize uint
88
93
cOut := serviceCall (c .svc , callName , string (inBytes ), uint (len (inBytes )), & cOutSize )
89
94
90
- msg := GoByte (cOut , cOutSize )
95
+ msg := GoBytes (cOut , cOutSize )
96
+
97
+ // The bytes is allocated from the C API, thus we free it when copied it to Go bytes.
98
+ defer free (cOut , cOutSize )
91
99
92
100
if bytes .HasPrefix (msg , []byte ("ERROR:" )) {
93
101
return nil , errors .New (strings .TrimPrefix (string (msg ), "ERROR:" ))
@@ -102,8 +110,8 @@ func cApiCall[I interface {
102
110
return out , nil
103
111
}
104
112
105
- // GoByte copies a null-terminated char* to a Go string.
106
- func GoByte (c uintptr , length uint ) []byte {
113
+ // GoBytes copies a uintptr with length to go []byte
114
+ func GoBytes (c uintptr , length uint ) []byte {
107
115
// We take the address and then dereference it to trick go vet from creating a possible misuse of unsafe.Pointer
108
116
ptr := * (* unsafe .Pointer )(unsafe .Pointer (& c ))
109
117
if ptr == nil {
0 commit comments