简体   繁体   English

c#中制作的dll可以在golang应用程序中使用吗

[英]Can a dll made in c# be used in a golang application

I have created a basic class that adds two numbers in c#.我创建了一个在 c# 中添加两个数字的基本类。 I have built it into a dll but when attempting to call it in golang I am unsuccessful.我已经将它构建到一个 dll 中,但是当我尝试在 golang 中调用它时我没有成功。

Is this possible currently in golang?目前在golang中这可能吗? If so can someone provide a example how to do this?如果是这样,有人可以提供一个如何做到这一点的例子吗?

Edit: I have included the last attempt I made at doing this.编辑:我已经包括了我做的最后一次尝试。 The C# dll is simply a method that adds the two numbers that are passed in. C# dll 只是一个将传入的两个数字相加的方法。

package main

import (
    "fmt"
    "syscall"
)

func main() {
    var mod = syscall.NewLazyDLL("MathForGo.dll")
    var proc = mod.NewProc("Add");
    proc.Call(2,3);
    fmt.Printf("%v",proc)
}

There is a project on Github that aims to do this. Github上有一个项目旨在实现这一目标。

https://github.com/matiasinsaurralde/go-dotnet https://github.com/matiasinsaurralde/go-dotnet

C# assemblies are not the same as C or C++ and will not load using syscall like we might want. C#程序集与C或C ++不同,不会像我们想要的那样使用syscall加载。

Edit: this answer should be deleted but SO won't let me do it. 编辑:这个答案应该删除,但不会让我这样做。 It does not actually work with C#. 它实际上不适用于C#。


Yes it is possible: https://github.com/golang/go/wiki/WindowsDLLs 是的,有可能: https//github.com/golang/go/wiki/WindowsDLLs

(Copying here in case the link dies) (如果链接死亡,请在此处复制)

There are a few ways to call "C" code from inside Go 有几种方法可以从Go内部调用“C”代码

First way: Dynamically load a dll, then call a method on it. 第一种方法:动态加载一个dll,然后在其上调用一个方法。 You can call the method via "syscallXX" (the XX is number of parameters, but if it has few than that, like if you need seven parameter, then syscall9 will still work, you just tell it the number of arguments is 7). 您可以通过“syscallXX”调用该方法(XX是参数的数量,但是如果它少于那个,就像您需要七个参数一样,那么syscall9仍然可以工作,您只需告诉它参数的数量是7)。 This way also works with Linux shared libraries, as well, if you're targeting linux: 如果你的目标是linux,这种方式也适用于Linux共享库:

A sample program that calls Windows DLLs from Go: 从Go调用Windows DLL的示例程序:

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

func abort(funcname string, err error) {
    panic(fmt.Sprintf("%s failed: %v", funcname, err))
}

var (
    kernel32, _        = syscall.LoadLibrary("kernel32.dll")
    getModuleHandle, _ = syscall.GetProcAddress(kernel32, "GetModuleHandleW")

    user32, _     = syscall.LoadLibrary("user32.dll")
    messageBox, _ = syscall.GetProcAddress(user32, "MessageBoxW")
)

const (
    MB_OK                = 0x00000000
    MB_OKCANCEL          = 0x00000001
    MB_ABORTRETRYIGNORE  = 0x00000002
    MB_YESNOCANCEL       = 0x00000003
    MB_YESNO             = 0x00000004
    MB_RETRYCANCEL       = 0x00000005
    MB_CANCELTRYCONTINUE = 0x00000006
    MB_ICONHAND          = 0x00000010
    MB_ICONQUESTION      = 0x00000020
    MB_ICONEXCLAMATION   = 0x00000030
    MB_ICONASTERISK      = 0x00000040
    MB_USERICON          = 0x00000080
    MB_ICONWARNING       = MB_ICONEXCLAMATION
    MB_ICONERROR         = MB_ICONHAND
    MB_ICONINFORMATION   = MB_ICONASTERISK
    MB_ICONSTOP          = MB_ICONHAND

    MB_DEFBUTTON1 = 0x00000000
    MB_DEFBUTTON2 = 0x00000100
    MB_DEFBUTTON3 = 0x00000200
    MB_DEFBUTTON4 = 0x00000300
)

func MessageBox(caption, text string, style uintptr) (result int) {
    var nargs uintptr = 4
    ret, _, callErr := syscall.Syscall9(uintptr(messageBox),
        nargs,
        0,
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))),
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))),
        style,
        0,
        0,
        0,
        0,
        0)
    if callErr != 0 {
        abort("Call MessageBox", callErr)
    }
    result = int(ret)
    return
}

func GetModuleHandle() (handle uintptr) {
    var nargs uintptr = 0
    if ret, _, callErr := syscall.Syscall(uintptr(getModuleHandle), nargs, 0, 0, 0); callErr != 0 {
        abort("Call GetModuleHandle", callErr)
    } else {
        handle = ret
    }
    return
}

func main() {
    defer syscall.FreeLibrary(kernel32)
    defer syscall.FreeLibrary(user32)

    fmt.Printf("Return: %d\n", MessageBox("Done Title", "This test is Done.", MB_YESNOCANCEL))
}

func init() {
    fmt.Print("Starting Up\n")
}

Second way is via syscall.NewProc (etc.) instead of syscall.GetProcAddress. 第二种方法是通过syscall.NewProc(等)而不是syscall.GetProcAddress。 These are basically some helper methods over the syscall ones, you saw above, and are available in Windows only: http://golang.org/src/pkg/syscall/dll_windows.go 这些基本上是一些辅助方法,而不是上面提到的系统调用方法,并且仅在Windows中提供: http//golang.org/src/pkg/syscall/dll_windows.go

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

func main() {
    var mod = syscall.NewLazyDLL("user32.dll")
    var proc = mod.NewProc("MessageBoxW")
    var MB_YESNOCANCEL = 0x00000003

    ret, _, _ := proc.Call(0,
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Done Title"))),
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("This test is Done."))),
        uintptr(MB_YESNOCANCEL))
    fmt.Printf("Return: %d\n", ret)

}

A third way would be to call into libraries basically by "linking" against the library, using the "cgo" method (this way works in Linux and Windows): 第三种方法是使用“cgo”方法(这种方式适用于Linux和Windows)基本上通过“链接”库来调用库:

This way would look something like this 这种方式看起来像这样

import ("C")
...
C.MessageBoxW(...)

See cgo for further details. 有关详细信息,请参阅cgo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM