Maison > Article > développement back-end > Comment définir la fonction Golang comme fonction de rappel de .net aot
J'ai un projet au travail. Le programme principal est écrit en Golang, et il existe également une bibliothèque partagée écrite en C# .Net AOT.
Le projet nécessite d'appeler des fonctions entre le code Golang et C# .Net AOT.
Le contenu spécifique est de passer une fonction Golang comme fonction de rappel en C# et de l'appeler en C#. Mais lorsque je l'ai testé, j'ai constaté que la fonctionnalité ne fonctionnait pas correctement.
Voici mon code de test :
En 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; } } }
Commande de compilation :
dotnet 发布 -p:NativeLib=共享 -r win-x64 -c 调试
Allez code :
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) }
J'ai implémenté une simple fonction Add(int a, int b) pour les tests. Les paramètres d'entrée sont 1 et 2, le résultat devrait être 3, mais ce n'est pas le cas. Lors du débogage, j'ai découvert que la liste des paramètres de la fonction de rappel n'était pas 1 et 2, mais des nombres étranges. J'ai essayé les deux conventions d'appel, Stdcall et Cdecl, mais elles n'ont pas pu résoudre le problème.
Quelle est la cause et comment la résoudre ?
Débogage
Voici le journal de sortie complet
<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>
Vous devez utiliser cgo pour exporter les fonctions 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) }
Le résultat est :
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!