如何使用Golang构建带有回调函数的C-shared库DLL
如何使用Golang构建带有回调函数的C-shared库DLL 你好! 我尝试用Go创建一个库(dll),并接收来自其他语言的函数作为回调使用。
package main
import "C"
import "fmt"
type externFunc func(int)
//export Connect
func Connect(callback externFunc) {
fmt.Println("cb ",callback)
for i:= 0; i<3;i++{
// 这是从C#接收的函数/方法,并尝试从Go中执行
callback(i)
}
}
这是运行我的应用程序时出现的错误。
错误
unexpected fault address 0xffffffffffffffff
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0xffffffffffffffff pc=0x627ca9ab]
接收回调的正确方法是什么?
更多关于如何使用Golang构建带有回调函数的C-shared库DLL的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于如何使用Golang构建带有回调函数的C-shared库DLL的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中创建C-shared库并处理回调函数时,需要遵循C的调用约定。你的代码有几个关键问题需要修正:
- 回调类型定义:必须使用
C类型来定义回调函数签名 - 函数导出:需要正确的导出声明
- 内存安全:避免Go的垃圾回收影响C函数指针
以下是修正后的代码:
package main
/*
#include <stdint.h>
// 定义回调函数类型
typedef void (*callback_func)(int);
*/
import "C"
import (
"fmt"
"unsafe"
)
// 全局变量存储回调函数
var callback C.callback_func
//export Connect
func Connect(cb C.callback_func) {
fmt.Println("Received callback from C#")
// 存储回调函数避免被GC回收
callback = cb
// 通过C调用执行回调
for i := 0; i < 3; i++ {
C.callback_func(cb)(C.int(i))
}
}
//export CallWithValue
func CallWithValue(value C.int) {
if callback != nil {
C.callback_func(callback)(value)
}
}
//export SetCallback
func SetCallback(cb C.callback_func) {
callback = cb
}
// 清理函数,避免内存泄漏
//export Cleanup
func Cleanup() {
callback = nil
}
func main() {
// 空main函数,C-shared库需要
}
编译命令:
go build -buildmode=c-shared -o mylib.dll
C#调用示例:
using System;
using System.Runtime.InteropServices;
class Program
{
// 定义回调委托
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CallbackDelegate(int value);
// DLL导入
[DllImport("mylib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Connect(CallbackDelegate callback);
[DllImport("mylib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetCallback(CallbackDelegate callback);
[DllImport("mylib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void CallWithValue(int value);
[DllImport("mylib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Cleanup();
// 回调函数实现
public static void MyCallback(int value)
{
Console.WriteLine($"C# callback received: {value}");
}
static void Main()
{
// 创建委托实例
CallbackDelegate callback = MyCallback;
// 调用Go函数
Connect(callback);
// 或者分开设置和执行
SetCallback(callback);
CallWithValue(42);
// 清理
Cleanup();
}
}
关键修正点:
- 使用
C.callback_func类型而不是Go函数类型 - 通过
C.callback_func(cb)(C.int(i))语法进行类型转换和调用 - 全局存储回调函数防止被垃圾回收
- 提供清理函数避免内存泄漏
- 确保C#侧使用
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]属性
错误原因分析:原始代码尝试直接调用Go类型的函数指针,这违反了C的调用约定,导致内存访问违规。必须通过C类型系统进行正确的类型转换和调用。

