在c#中制作的dll可以用在golang应用程序中 [英] Can a dll made in c# be used in a golang application

查看:206
本文介绍了在c#中制作的dll可以用在golang应用程序中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个在c#中添加两个数字的基本类。我已经将它构建成一个dll,但是当试图在golang中调用它时,我不成功。首先,这可能是目前在golang?如果是的话,有人可以提供一个例子如何做到这一点?



编辑:我已经包括了我在做这件事的最后一次尝试。 C#的dll只是一个方法,它添加了两个传入的数字。

  package main 

导入(
fmt
系统调用


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


解决方案

可以: https://github.com/golang/go/wiki/ WindowsDLL



(在链接死亡的情况下复制)


有几种方法可以从Go内部调用C代码

第一种方法:动态加载dll,然后调用一个方法。你可以用
通过syscallXX调用这个方法(XX是参数的数量,但是
如果它少于这个数量,就像你需要七个参数一样,那么
syscall9仍然可以工作,你只需告诉它参数的数量是
7)。这种方式也适用于Linux共享库,如果
是针对Linux的:



从Go调用Windows DLL的示例程序: p>



 包主

导入(
fmt
系统调用
不安全


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 )



MB_OK = 0x00000000
MB_OKCANCEL = 0x00000001
MB_ABORTRETRYIGNORE = 0x00000002
MB_YESNOCANCEL = 0x00000003
MB_YESNO = 0x00000004
MB_RETRYCANCEL = 0x 00000005
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。指针(syscall.StringToUTF16Ptr(标题))),
样式,
0 ,
0,
0,
0,
0)
如果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第二种方法是:第二种方法是使用第二种方法通过syscall.NewProc(等)而不是
syscall.GetProcAddress。这些基本上是一些帮助程序方法,超过了
的系统调用方法,您可以在上面看到,并且仅在Windows中提供:
http://golang.org/src/pkg/syscall/dll_windows.go




 包主要

导入(
fmt
系统调用
不安全


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 (Return:%d \ n,ret)
$(This test is Done。))),
uintptr(MB_YESNOCANCEL))
fmt.Printf b $ b}




第三种方法是基本调用库通过使用t将
与图书馆链接他的cgo方法(这种方式可以在Linux
和Windows中运行):



这种方式看起来像这样



 导入(C)
...
C.MessageBoxW(...)




请参阅 cgo 以获得更多详细信息。



I have created a basic class that adds two numbers in c#. I have built it into a dll but when attempting to call it in golang I am unsuccessful. First is this possible currently in 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.

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

解决方案

Yes it is possible: 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

First way: Dynamically load a dll, then call a method on it. 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). This way also works with Linux shared libraries, as well, if you're targeting linux:

A sample program that calls Windows DLLs from Go:

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

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

This way would look something like this

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

See cgo for further details.

这篇关于在c#中制作的dll可以用在golang应用程序中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆