Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk menetapkan fungsi golang sebagai fungsi panggil balik .net aot

Bagaimana untuk menetapkan fungsi golang sebagai fungsi panggil balik .net aot

WBOY
WBOYke hadapan
2024-02-05 22:06:081041semak imbas

如何将golang函数设置为.net aot的回调函数

Kandungan soalan

Saya ada projek di tempat kerja Program utama ditulis dalam Golang, dan terdapat juga perpustakaan kongsi yang ditulis dalam C# .Net AOT.

Projek ini memerlukan fungsi panggilan antara kod Golang dan C# .Net AOT.

Kandungan khusus adalah untuk menghantar fungsi Golang sebagai fungsi panggil balik kepada C# dan memanggilnya dalam C#. Tetapi apabila saya mengujinya, saya mendapati bahawa ciri itu tidak berfungsi dengan betul.

Ini kod ujian saya:

Dalam 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;
        }
    }
}

Arahan kompilasi: dotnet 发布 -p:NativeLib=共享 -r win-x64 -c 调试

Kod pergi:

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)
}

Saya melaksanakan fungsi Tambah(int a, int b) mudah untuk ujian. Parameter input adalah 1 dan 2, hasilnya harus 3, tetapi tidak. Apabila saya menyahpepijat, saya mendapati bahawa senarai parameter fungsi panggil balik bukanlah 1 dan 2, tetapi beberapa nombor pelik. Saya mencuba kedua-dua konvensyen panggilan, Stdcall dan Cdecl, tetapi mereka tidak dapat menyelesaikan masalah itu.

Apakah punca dan cara mengatasinya?

Nyahpepijat

Ini ialah log keluaran lengkap

<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>

Jawapan betul


Anda perlu menggunakan cgo untuk mengeksport fungsi 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)
}

Keluaran ialah:

Atas ialah kandungan terperinci Bagaimana untuk menetapkan fungsi golang sebagai fungsi panggil balik .net aot. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam