
本文详解如何在 windows 64 位环境下,通过 cgo 机制让独立编译的 c++ dll 安全、可靠地回调 go 导出函数,涵盖函数指针传递、c 接口封装、线程安全处理及常见陷阱规避。
本文详解如何在 windows 64 位环境下,通过 cgo 机制让独立编译的 c++ dll 安全、可靠地回调 go 导出函数,涵盖函数指针传递、c 接口封装、线程安全处理及常见陷阱规避。
在 Go 中实现从外部 C++ DLL 的回调,核心在于:Go 必须向 C 暴露可被 C 函数指针类型接收并调用的 C 兼容函数,且该函数需满足 C ABI 要求(如使用 //export 标记、无 Go 运行时依赖、避免栈上分配 Go 对象)。关键步骤如下:
✅ 1. 在 Go 中定义并导出回调函数
使用 //export 注释声明函数,并确保签名完全匹配 C 端预期(参数与返回值均为 C 基本类型或 *C.xxx):
package main
/*
#include <stdint.h>
// 声明 C 回调函数类型(与 DLL 中 typedef 一致)
typedef void (*callback_fn)(int32_t code, const char* msg);
*/
import "C"
import "unsafe"
//export goCallbackHandler
func goCallbackHandler(code C.int32_t, msg *C.char) {
// 注意:msg 是 C 字符串,需转为 Go 字符串(仅读取,不修改)
if msg != nil {
s := C.GoString(msg)
println("DLL callback received:", s, "code =", int(code))
}
}
func main() {
// 将 Go 函数地址转换为 C 函数指针,传给 DLL
cbPtr := (C.callback_fn)(unsafe.Pointer(C.goCallbackHandler))
// 假设 DLL 提供了 register_callback 函数
C.register_callback(cbPtr)
// 保持主 goroutine 运行(防止程序退出)
select {}
}✅ 2. C++ DLL 端正确声明与调用回调
在 DLL 头文件中定义一致的函数指针类型,并确保调用前已保存 Go 传入的函数指针:
// callback.h
#ifdef EXPORTING_DLL
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
typedef void (*callback_fn)(int32_t code, const char* msg);
extern "C" {
DLL_API void register_callback(callback_fn cb);
DLL_API void trigger_event(); // 示例:触发回调
}
// callback.cpp
static callback_fn g_callback = nullptr;
extern "C" {
DLL_API void register_callback(callback_fn cb) {
g_callback = cb; // 保存 Go 传入的函数指针
}
DLL_API void trigger_event() {
if (g_callback) {
g_callback(42, "Hello from C++ DLL!");
}
}
}⚠️ 重要注意事项
-
线程安全:Go 回调函数运行在 C 线程上,不可直接调用 Go 运行时函数(如
fmt.Println, channel 操作、runtime.GC());若需跨线程交互,应通过runtime.LockOSThread()+cgo配合chan或sync.Mutex协作。 -
字符串生命周期:C 传入的
const char*由 C 内存管理,Go 中必须用C.GoString(复制)或C.CString(需手动C.free)处理,*切勿直接保存 `C.char` 指针长期使用**。 -
Windows 平台 ABI:确保 Go 编译为
GOOS=windows GOARCH=amd64,DLL 为 x64 构建,调用约定默认为__cdecl(CGO 自动适配)。 -
链接与构建:Go 侧需启用
CGO_ENABLED=1,DLL 需导出 C 符号(extern "C"防止 C++ name mangling),并在 Go 的#cgo LDFLAGS中指定.lib文件路径。
? 提示:官方文档是权威参考——CGO Wiki: Function Pointer Callbacks 明确说明了函数指针转换规则与限制,建议作为开发时首要查阅资料。
立即学习“C++免费学习笔记(深入)”;
通过以上结构化实践,即可在 Windows 下稳定实现 C++ DLL 到 Go 的双向互操作,兼顾性能与安全性。


















