Ich habe ein Projekt bei der Arbeit. Das Hauptprogramm ist in Golang geschrieben, und es gibt auch eine gemeinsam genutzte Bibliothek, die in C# .Net AOT geschrieben ist.
Das Projekt erfordert den Aufruf von Funktionen zwischen Golang-Code und C# .Net AOT.
Der spezifische Inhalt besteht darin, eine Golang-Funktion als Rückruffunktion an C# zu übergeben und sie in C# aufzurufen. Aber als ich es getestet habe, stellte ich fest, dass die Funktion nicht richtig funktionierte.
Das ist mein Testcode:
In 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; } } }
Kompilierungsbefehl:
dotnet 发布 -p:NativeLib=共享 -r win-x64 -c 调试
Go-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) }
Ich habe zum Testen eine einfache Add(int a, int b)-Funktion implementiert. Die Eingabeparameter sind 1 und 2, das Ergebnis sollte 3 sein, ist es aber nicht. Beim Debuggen stellte ich fest, dass die Parameterliste der Rückruffunktion nicht 1 und 2, sondern einige seltsame Zahlen enthielt. Ich habe beide Aufrufkonventionen ausprobiert, Stdcall und Cdecl, aber sie konnten das Problem nicht lösen.
Was ist die Ursache und wie kann man sie lösen?
Debuggen
Dies ist das vollständige Ausgabeprotokoll
<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>
Sie müssen cgo verwenden, um Go-Funktionen zu exportieren
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) }
Die Ausgabe ist:
Das obige ist der detaillierte Inhalt vonSo legen Sie die Golang-Funktion als Callback-Funktion von .net aot fest. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!