返回顶部
首页 > 资讯 > 后端开发 > GO >如何将golang函数设置为.net aot的回调函数
  • 591
分享到

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

2024-02-05 21:02:07 591人浏览 安东尼
摘要

问题内容 我工作中有一个项目,主程序是用golang编写的,还有一个用C# .net AOT编写的共享库。 项目中需要Golang代码和C# .Net AOT之间调用函数。 具体内容是

问题内容

我工作中有一个项目,主程序是用golang编写的,还有一个用C# .net AOT编写的共享库。

项目中需要Golang代码和C# .Net AOT之间调用函数。

具体内容是将一个Golang函数作为回调函数传递给C#,并在C#中调用。但当我测试时,发现该功能无法正常使用。

这是我的测试代码:

在 C# 中:

using System.Runtime.InteropServices;

namespace CSharp_Go
{
    public unsafe class Export
    {
        private static delegate* unmanaged[Stdcall] _aDDDel;
        [UnmanagedCallersOnly(EntryPoint = "SetAddFunc")]
        public static void SetAddFunc(delegate* unmanaged[Stdcall] addDel)
        {
            _addDel = addDel;
        }

        private static delegate* unmanaged _testFun;
        [UnmanagedCallersOnly(EntryPoint = "SetTestFunc")]
        public static void SetTestFunc(delegate* unmanaged 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;
        }
    }
}

编译命令: dotnet 发布 -p:NativeLib=共享 -r win-x64 -c 调试

Go 代码:

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

我实现了一个简单的 Add(int a, int b) 函数进行测试。输入参数是1和2,结果应该是3,但事实并非如此。我调试的时候发现回调函数的参数列表不是1和2,而是一些奇怪的数字。我尝试了两种调用约定,Stdcall和Cdecl,但他们无法解决这个问题。

这是什么原因以及如何解决?

调试

这是完整的输出日志


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.


正确答案


需要使用cgo导出go函数

package main


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

输出是:

以上就是如何将golang函数设置为.net aot的回调函数的详细内容,更多请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: 如何将golang函数设置为.net aot的回调函数

本文链接: https://lsjlt.com/news/561101.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何将golang函数设置为.net aot的回调函数
    问题内容 我工作中有一个项目,主程序是用Golang编写的,还有一个用C# .Net AOT编写的共享库。 项目中需要Golang代码和C# .Net AOT之间调用函数。 具体内容是...
    99+
    2024-02-05
  • golang函数中回调函数的作用
    go 中回调函数在函数中作为参数传递,用于在特定事件或条件发生后执行特定动作,增强代码的可重用性和扩展性。主要作用为:事件处理:作为事件侦听器的回调处理程序,在事件发生时采取动作。数据处...
    99+
    2024-04-25
    golang 回调函数 git
  • PHP 函数如何返回回调函数?
    php 函数可以通过使用以下语法返回回调函数:定义函数以返回回调函数:function returncallback(): callable回调函数可以接受任何参数并返回任何类型的值确保...
    99+
    2024-04-10
    php 回调函数
  • Golang函数的回调函数应用讲解
    Golang作为一门高效的编程语言,其函数的回调函数应用极为重要,因此在本篇文章中,我们将深入讲解Golang函数的回调函数应用的相关知识。一、什么是回调函数?回调函数就是函数指针,它作为参数直接传给其他函数。当这个参数函数执行完毕后,再回...
    99+
    2023-05-16
    Golang函数 回调函数 应用讲解
  • 如何在 Golang 中使用数据库回调函数?
    在 golang 中使用数据库回调函数可以实现:在指定数据库操作完成后执行自定义代码。通过单独的函数添加自定义行为,无需编写额外代码。回调函数可用于插入、更新、删除和查询操作。必须使用 ...
    99+
    2024-05-14
    数据库 回调函数 mysql git golang
  • .val如何将函数作为参数设置文本框的值
    这篇文章主要为大家展示了“.val如何将函数作为参数设置文本框的值”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“.val如何将函数作为参数设置文本框的值”这篇文...
    99+
    2024-04-02
  • PHP如何用回调函数迭代地将数组简化为单一的值
    这篇文章将为大家详细讲解有关PHP如何用回调函数迭代地将数组简化为单一的值,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。使用回调函数迭代简化数组到单一值 概述 PHP提供了简洁的方法来使用回调函数迭代数组...
    99+
    2024-04-02
  • 如何使用 Golang 函数类型实现回调?
    是的,在 go 中可以使用函数类型实现回调功能,具体步骤如下:声明一个函数类型,指定回调函数的签名。定义一个接受函数类型作为参数的函数。将需要回调的函数传递给该函数。 使用 Golan...
    99+
    2024-04-22
    golang 回调
  • 如何在 PHP 中使用函数作为回调?
    在 php 中使用函数作为回调,可以使用匿名函数或命名函数。匿名函数语法为:$callback = function ($argument) { return $result; }。命名...
    99+
    2024-04-10
    php 回调函数
  • Golang函数如何返回多值?
    go 中函数可以通过逗号分隔的多个变量返回多个值。语法为:func functionname(parameters) (returnvalue1, returnvalue2, ..., ...
    99+
    2024-04-11
    golang 多值返回
  • 如何调试并发 Golang 函数?
    调试并发 go 函数的技巧:使用 fmt.println() 打印变量值或消息了解执行流和变量状态。使用 go test 写测试用例检查并发函数的正确行为。在支持并发调试的 ide 中逐...
    99+
    2024-04-17
    golang 并发
  • 如何调试golang函数闭包
    使用 debugger 调试 go 闭包的方法:使用 debugger 包添加一个 debugger 调用到程序入口点;使用调试器客户端连接到调试器端口并设置断点。 如何调试 Go 中...
    99+
    2024-04-23
    golang 闭包 git 标准库
  • Java如何实现回调函数
    小编给大家分享一下Java如何实现回调函数,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在WINDOWS中,程序员想让系统DLL调用自己编写的一个方法,于是利用D...
    99+
    2023-05-30
    java
  • keras回调函数如何使用
    这篇文章主要介绍了keras回调函数如何使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇keras回调函数如何使用文章都会有所收获,下面我们一起来看看吧。回调函数回调函数是一个对象(实现了特定方法的类实例),...
    99+
    2023-07-05
  • Golang 函数文档中如何表示函数的返回值?
    在 golang 函数文档中,函数的返回值可以使用以下语法表示:func foo() (output1 type1, output2 type2, ..., outputn typen)...
    99+
    2024-04-18
    golang 函数返回值
  • PHP如何为数组的每个元素应用回调函数
    这篇文章将为大家详细讲解有关PHP如何为数组的每个元素应用回调函数,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 php中使用回调函数处理数组元素 简介 PHP 中的 array_map() 函数允许您...
    99+
    2024-04-02
  • python中以函数作为参数(回调函数)的实现方法
    目录python以函数作为参数(回调函数)python函数的参数类型一、必须参数二、关键字参数三、默认参数四、不定长参数总结python以函数作为参数(回调函数) 纯粹是自己学习总结...
    99+
    2023-01-04
    python函数 python函数为参数 python回调函数
  • C++11 成员函数作为回调函数的使用方式
    目录C++11成员函数作为回调函数使用示例1示例2类成员函数作为回调函数的方法及注意点类成员函数当回调函数的方法为什么回调函数必须为静态函数?类的静态成员函数如何访问非静态成员?C+...
    99+
    2022-11-13
    C++11 成员函数 C++11 回调函数 使用回调函数
  • golang函数的返回值如何实现
    这篇文章主要介绍“golang函数的返回值如何实现”,在日常操作中,相信很多人在golang函数的返回值如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”golang函数的返回值如何实现”的疑惑有所帮助!...
    99+
    2023-07-05
  • 如何设置golang函数的覆盖率目标?
    使用 coverpackage 函数设置覆盖率目标:为要覆盖的包设置目标。为收集覆盖率数据指定包。在 init() 函数中调用 coverpackage。通过设置目标,我们可以识别测试中...
    99+
    2024-04-26
    golang 覆盖率目标
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作