@@ -18,11 +18,12 @@ import (
1818var libInit sync.Once
1919
2020var (
21+ client * NativeServiceClient
2122 lib uintptr
2223 serviceNew func (uint64 ) uintptr
2324 serviceDelete func (uintptr )
2425 serviceCall func (uintptr , string , string , uint , * uint ) uintptr
25- freeString func (uintptr )
26+ free func (uintptr , uint )
2627)
2728
2829type validator interface {
@@ -33,13 +34,20 @@ type NativeServiceClient struct {
3334 svc uintptr
3435}
3536
36- func initLib ( ) {
37+ func initClient ( pluginAgent uint64 ) {
3738 libInit .Do (func () {
3839 lib , _ = loadServiceNativeLib ()
3940 purego .RegisterLibFunc (& serviceNew , lib , "kclvm_service_new" )
4041 purego .RegisterLibFunc (& serviceDelete , lib , "kclvm_service_delete" )
4142 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+ })
4351 })
4452}
4553
@@ -48,16 +56,13 @@ func NewNativeServiceClient() api.ServiceClient {
4856}
4957
5058func 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 )
6166}
6267
6368func cApiCall [I interface {
@@ -87,7 +92,10 @@ func cApiCall[I interface {
8792 var cOutSize uint
8893 cOut := serviceCall (c .svc , callName , string (inBytes ), uint (len (inBytes )), & cOutSize )
8994
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 )
9199
92100 if bytes .HasPrefix (msg , []byte ("ERROR:" )) {
93101 return nil , errors .New (strings .TrimPrefix (string (msg ), "ERROR:" ))
@@ -102,8 +110,8 @@ func cApiCall[I interface {
102110 return out , nil
103111}
104112
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 {
107115 // We take the address and then dereference it to trick go vet from creating a possible misuse of unsafe.Pointer
108116 ptr := * (* unsafe .Pointer )(unsafe .Pointer (& c ))
109117 if ptr == nil {
0 commit comments