
我工作中有一个项目,主程序是用Golang编写的,还有一个用C# .Net AOT编写的共享库。
项目中需要Golang代码和C# .Net AOT之间调用函数。
具体内容是将一个Golang函数作为回调函数传递给C#,并在C#中调用。但当我测试时,发现该功能无法正常使用。
这是我的测试代码:
立即学习“go语言免费学习笔记(深入)”;
在 C# 中:
using System.Runtime.InteropServices;
namespace CSharp_Go
{
public unsafe class Export
{
private static delegate* unmanaged[Stdcall]<int, int, int> _addDel;
[UnmanagedCallersOnly(EntryPoint = "SetAddFunc")]
public static void SetAddFunc(delegate* unmanaged[Stdcall]<int, int, int> addDel)
{
_addDel = addDel;
}
private static delegate* unmanaged<int> _testFun;
[UnmanagedCallersOnly(EntryPoint = "SetTestFunc")]
public static void SetTestFunc(delegate* unmanaged<int> testFun)
{
_testFun = testFun;
}
[UnmanagedCallersOnly(EntryPoint = "Test")]
public static int Test()
{
int res = _testFun();
Console.WriteLine($"in c# Test res:{res}");
return res;
}
[UnmanagedCallersOnly(EntryPoint = "Add")]
public static int Add(int a, int b)
{
Console.WriteLine($"in c# Add a:{a}, b:{b}");
int res = 0;
if (null != _addDel)
{
res = _addDel(a, b);
Console.WriteLine($"in c# Add res:{res}, a:{a}, b:{b}");
}
return res;
}
}
}编译命令:
dotnet 发布 -p:NativeLib=共享 -r win-x64 -c 调试
Go 代码:
package main
import (
"C"
"fmt"
"reflect"
"syscall"
"unsafe"
)
func Sum(a, b int32) int32 {
//fmt.Printf("a:%d, b:%d\n", a, b)
res := a + b
return res
}
func main() {
f := Sum
ptrValue := reflect.ValueOf(f)
ptr := unsafe.Pointer(ptrValue.Pointer())
addr := uintptr(ptr)
fmt.Printf("Func Addr: %v\n", addr)
var input string
fmt.Scanln(&input)
fmt.Println(input)
var aValue int32 = int32(1)
var bValue int32 = int32(2)
var a uintptr = uintptr(aValue)
var b uintptr = uintptr(bValue)
ptrVa := &aValue
ptrA := &a
fmt.Printf("va:%v, a: %v\n", ptrVa, ptrA)
t := func() int32 {
//fmt.Println(aValue, bValue)
//pa := (*int32)(unsafe.Pointer(uintptr(aValue)))
//a := *pa
return aValue + bValue
}
ptrT := uintptr(unsafe.Pointer(reflect.ValueOf(t).Pointer()))
fmt.Printf("Func Addr: %v\n", ptrT)
fmt.Println("Hello go c#")
maindll := syscall.NewLazyDLL("CSharp_Go.dll")
setTestFunc := maindll.NewProc("SetTestFunc")
test := maindll.NewProc("Test")
//cb := syscall.NewCallback(t)
r1, r2, err := setTestFunc.Call(ptrT)
fmt.Println(r1, r2, err)
r1, r2, err = test.Call()
fmt.Println(r1, r2, err)
setAddFunc := maindll.NewProc("SetAddFunc")
add := maindll.NewProc("Add")
r1, r2, err = setAddFunc.Call(addr)
fmt.Println(r1, r2, err)
r1, r2, err = add.Call(a, b)
fmt.Println(r1, r2, err)
fmt.Scanln(&input)
fmt.Println(input)
}我实现了一个简单的 Add(int a, int b) 函数进行测试。输入参数是1和2,结果应该是3,但事实并非如此。我调试的时候发现回调函数的参数列表不是1和2,而是一些奇怪的数字。我尝试了两种调用约定,Stdcall和Cdecl,但他们无法解决这个问题。
这是什么原因以及如何解决?
调试
这是完整的输出日志
<code> Func Addr: 15405888 6 6 va:0xc00000e128, a: 0xc00000e130 Func Addr: 15410016 Hello go c# 2259596893072 2260255909544 The operation completed successfully. in c# Test res:12144 12144 0 The operation completed successfully. 2259596893072 15405888 The operation completed successfully. in c# Add a:1, b:2 in c# Add res:31533024, a:1, b:2 31533024 0 The operation completed successfully. </code>
需要使用cgo导出go函数
package main
/*
extern int sum(int, int);
//static inline void CallMyFunction(int a, int b) {
// sum(a, b);
//}
*/
import "C"
import (
"fmt"
"reflect"
"syscall"
"unsafe"
)
//export sum
func sum(a, b C.int) C.int {
res := a + b
fmt.Println(a, "+", b , "=", res )
return res
}
func main() {
fmt.Println("Hello go c#")
var input string
fmt.Scanln(&input)
fmt.Println(input)
//C.CallMyFunction(3, 4)
var aValue int32 = int32(3)
var bValue int32 = int32(4)
var a uintptr = uintptr(aValue)
var b uintptr = uintptr(bValue)
f := C.sum
ptrValue := reflect.ValueOf(f)
ptr := unsafe.Pointer(ptrValue.Pointer())
addr := uintptr(ptr)
fmt.Printf("Func Addr: %v\n", addr)
maindll := syscall.NewLazyDLL("CSharp_Go.dll")
//maindll := syscall.NewLazyDLL("Cpp_Go.dll")
setAddFunc := maindll.NewProc("SetAddFunc")
add := maindll.NewProc("Add")
r1, r2, err := setAddFunc.Call(addr)
fmt.Println(r1, r2, err)
r1, r2, err = add.Call(a, b)
fmt.Println(r1, r2, err)
fmt.Scanln(&input)
fmt.Println(input)
}输出是:
以上就是如何将golang函数设置为.net aot的回调函数的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号