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

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

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Lepaskan: 2024-02-05 22:06:08
ke hadapan
1110 orang telah melayarinya

如何将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;
        }
    }
}
Salin selepas log masuk

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)
}
Salin selepas log masuk

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>
Salin selepas log masuk


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)
}
Salin selepas log masuk

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 Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan