至少目前来说此路不通……
对于 C 的了解仅限于 Hello World ,链接、符号什么的一无所知,所以其实一开始就是抗拒 CGO 的,打算的就是使用 UDS 来实现外部的数据库驱动。但是数据库驱动的 Rows 和 Tx 都是不可恢复对象,如果进程挂了,即使重启之后状态也都对应不上,此时只能强行关闭相关的 UI 。——这体验也太糟糕了。
所以开始调研使用 CGO 来加载由 Go 编译的动态库。在 github 的 issues 里有一些关于这方面的讨论,都是说不可行。但是看到了 purego ,尝试之后发现真的可以工作! windows 和 linux 上都没有问题。实现方式是,仅暴露了 4 个函数,DllVersion
, DllOpenObj
, DllCall
和DllCancel
,传递的参数都是 uintptr,且没有返回值。返回值的内存由主程序生成,当作参数传递,然后 Dll 里面使用 JSON 序列化后写入。——至少在 windows/linux 上这么做是可以的。虽然需要序列化,但是还是要比通过 UDS 来做要好。
我没有 Mac 的设备,但是我觉得 linux 都没有问题,那应该也没事。
我做好了 Dll 的加载和简单的管理,在准备发布前的测试时,我使用 quckemu 成功的运行了 MacOs 的虚拟机。却发现在 Mac 上不论是 purego 还是 plgin 都不能成功的运行由 Go 编译的动态库。purego 可能是 dll 内部的 Go Runtime 没有初始化,plugin 可能是数据库的驱动是依赖 CGO 的缘故。
总之,我很失望,至少目前来说此路不通……
UDS 又有状态不能同步的问题,所以只能取消外部数据库驱动这个功能,全部都打包到一起了……😓
1
assiadamo 41 天前
不知道你的应用场景使用共享内存 shardmem 如何
|
2
Sendya 41 天前
|
3
liaohongxing 41 天前
这块关注很久了,可以看下我收藏的这个库 https://github.com/JupiterRider/ffi , 也是 purego 的一个扩展优化
|
4
liaohongxing 41 天前
用 libffi 调用 dll 或 so 库比较靠谱
|
5
crackidz 41 天前
purego 主要是用于跨语言调用一些库用的,比如说 std library ,一些其他现成的 C 库。
|
![]() |
6
suruiran OP @liaohongxing 我感觉都差不多,主要是 go 的 dll 里面还有个运行时。……我暂时不想再尝试了。
|
7
ExplodingFKL 41 天前
|
![]() |
8
suruiran OP @ExplodingFKL 这就 UDS 呀。我做的是一个通用的桌面端数据库管理应用。Rows 跟 Tx 这些重启之后没办法恢复呀……这时候 UI 怎么办?
|
![]() |
9
lysShub 41 天前
你这帖子没前没后的,没有个上下文啊?
1. “但是数据库驱动的 Rows 和 Tx 都是不可恢复对象,如果进程挂了,即使重启之后状态也都对应不上,此时只能强行关闭相关的 UI 。——这体验也太糟糕了” : 纯属多虑了,不要钻牛角尖 2. “所以开始调研使用 CGO 来加载由 Go 编译的动态库”:既然两个都是 go 写的,为啥不合在一起 ? 3. “Mac 上不论是 purego 还是 plgin 都不能成功的运行由 Go 编译的动态库”:最新版本,这两个的文档里都有提到支持 mac 的;多半是你虚拟机问题,搞 cgo 就不要跨平台编译了,更不要用什么虚拟机 |
10
iceheart 40 天前 via Android
把插件功能单跑一个进程,用 grpc 调用不行么?
|
11
Silicon 40 天前
为什么是「调研使用 CGO 来加载由 Go 编译的动态库」而不是直接使用 https://pkg.go.dev/plugin ,从你的描述中我好像没看到和这个能力冲突的需求
|
12
Silicon 40 天前
哦你要支持 windows……那么 go plugin 不行。
purego 显然也不可以,这里不只是没有 runtime 的问题,还有当两个 runtime 在同一个进程里存活时是不是有打架的风险,我不好说,我觉得至少协程调度的时候如果双方互相不认得对方,可能会有很微妙的问题。 |
14
bli22ard 40 天前
没看明白,你想表达什么
|
15
hez2010 39 天前
一个进程内无法加载多个 go 的 runtime ,参考官方仓库的 issue: https://github.com/golang/go/issues/50304#issuecomment-999302888
并且他们也没有计划修复。 |
17
hez2010 39 天前
@suruiran Go runtime 的特性其实也决定了 Go 不适合用来做动态链接库。如果一定要做动态链接库的话,建议更换其他语言,比如 C/C++/Rust ,又或者 C# 走 NativeAOT 编译出 native dll ,这些都是没问题的,并且同一个进程多 dll 共存也没有问题。
|
![]() |
18
sssxyd 38 天前
go 加载动态库的话,动态库是什么语言写的并没有区别,没理由 mac 上不行;
我本来也考虑过加载动态库作为插件的方案,不过无法控制权限,改用 wasm ; 你可以考虑一下 wasmtime-go, 公共 wasmtime 这个 rust 编写的 wasm runtime ,运行 wasm ; wasm 应该不会有适配问题 |
![]() |
19
PungentSauce 38 天前
用 grpc 也行的吧。 或者一些动态加载的脚本 ,traefik 的插件是用脚本的方式
|