feat(napi P1): Go-implemented libfivenode (c-shared) for the N-API bridge
Faithful port of the C++ fivenode topology — node hosts the existing N-API
addon, which now links a libfivenode implemented in Go (CGO c-shared)
instead of the Harbour-C core. cmd/libfivenode exports the C ABI the addon
expects (hb_bridge_init/shutdown/handle_request/last_error/set_auth/
clear_auth/free, tfn_register_callbacks). Build:
go build -buildmode=c-shared \
-ldflags="-extldflags=-Wl,-install_name,@rpath/libfivenode.dylib" \
-o native/output/darwin/libfivenode.dylib ./cmd/libfivenode
P1 proven: node → addon → Go hb_bridge_handle_request round-trips a
response in-process (no Harbour-C, no subprocess). P2 wires the real PRG
dispatcher; P3 the npm callbacks (tfn_register_callbacks → Require); P4
the node main-thread marshaling. (goja probe removed — pure-JS only,
insufficient for full npm.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@
|
||||
*.frb
|
||||
*.pgo
|
||||
*.log
|
||||
/native/output/
|
||||
|
||||
62
cmd/libfivenode/main.go
Normal file
62
cmd/libfivenode/main.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// cmd/libfivenode — Go c-shared 구현의 libfivenode (P1 스켈레톤).
|
||||
//
|
||||
// 기존 C++ fivenode N-API 애드온(fivenode.node)이 기대하는 C ABI 를 Go 가
|
||||
// CGO //export 로 제공한다. Harbour-C 코어를 Go 런타임으로 교체하는 첫 단계.
|
||||
//
|
||||
// go build -buildmode=c-shared -o ../../native/output/darwin/libfivenode.dylib ./cmd/libfivenode
|
||||
//
|
||||
// P1 목표: 심볼 export + 애드온 로드·왕복(canned 응답). 실제 PRG 디스패치/
|
||||
// npm 콜백은 P2~P4 에서.
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
//export hb_bridge_init
|
||||
func hb_bridge_init() C.int {
|
||||
return 1
|
||||
}
|
||||
|
||||
//export hb_bridge_shutdown
|
||||
func hb_bridge_shutdown() {}
|
||||
|
||||
//export hb_bridge_handle_request
|
||||
func hb_bridge_handle_request(reqJSON *C.char) *C.char {
|
||||
// P1: 고정 응답으로 node↔Go 왕복만 증명.
|
||||
_ = C.GoString(reqJSON)
|
||||
resp := `{"status":200,"headers":{"Content-Type":"text/plain; charset=utf-8"},"body":"hello from Go-implemented libfivenode (N-API P1)"}`
|
||||
return C.CString(resp)
|
||||
}
|
||||
|
||||
//export hb_bridge_last_error
|
||||
func hb_bridge_last_error() *C.char {
|
||||
return C.CString("")
|
||||
}
|
||||
|
||||
//export hb_bridge_set_auth
|
||||
func hb_bridge_set_auth(authJSON *C.char) {}
|
||||
|
||||
//export hb_bridge_clear_auth
|
||||
func hb_bridge_clear_auth() {}
|
||||
|
||||
//export hb_bridge_free
|
||||
func hb_bridge_free(ptr *C.char) {
|
||||
if ptr != nil {
|
||||
C.free(unsafe.Pointer(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
// tfn_register_callbacks — 애드온이 npm 콜백 묶음을 등록(P3 에서 저장·사용).
|
||||
// P1 에선 void* 로 받아 보관만(구조체 레이아웃은 P3 에서 정의).
|
||||
//
|
||||
//export tfn_register_callbacks
|
||||
func tfn_register_callbacks(cb unsafe.Pointer) {
|
||||
npmCallbacks = cb
|
||||
}
|
||||
|
||||
var npmCallbacks unsafe.Pointer
|
||||
|
||||
func main() {}
|
||||
6
go.mod
6
go.mod
@@ -2,12 +2,14 @@ module fivenode_go
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require five v0.0.0
|
||||
require (
|
||||
five v0.0.0
|
||||
github.com/jackc/pgx/v5 v5.9.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.9.2 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
|
||||
7
go.sum
7
go.sum
@@ -1,4 +1,6 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
@@ -7,13 +9,18 @@ github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw=
|
||||
github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
Reference in New Issue
Block a user