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!