Skip to content

Commit 7e88a1e

Browse files
authored
Merge pull request #149 from Peefy/feat-go-lib-handle-res-management
feat: use singleton for the client
2 parents 50ffba9 + 5219971 commit 7e88a1e

File tree

3 files changed

+25
-54
lines changed

3 files changed

+25
-54
lines changed

.github/workflows/go-test.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
test:
2525
strategy:
2626
matrix:
27-
os: [macos-12, macos-latest, ubuntu-20.04, ubuntu-latest, windows-latest]
27+
os: [macos-12, macos-latest, ubuntu-20.04, ubuntu-22.04, ubuntu-latest, windows-latest]
2828
runs-on: ${{ matrix.os }}
2929
defaults:
3030
run:

go/include/kclvm_cli_cdylib.h

-37
This file was deleted.

go/native/client.go

+24-16
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ import (
1818
var libInit sync.Once
1919

2020
var (
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

2829
type 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

5058
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)
6166
}
6267

6368
func 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

Comments
 (0)