doupi3874 2017-07-13 09:15
浏览 28

如何在自定义dll文件中调用函数

now i got this function describe like this

int ReadCard(char *room,char *gate,char *stime, char *guestname, char *guestid, char *lift, char *track1, char *track2, long *cardno, int *st, int *Breakfast);`

and this is what i do

room := ""
gate := ""
stime := ""
guestname := ""
guestid := ""
lift := ""
track1 := ""
track2 := ""
cardno := int64(0)
st := int64(0)
Breakfast := int64(0)

MAINDLL, _ := syscall.LoadLibrary("xxxxx.dll")
defer syscall.FreeLibrary(MAINDLL)
readCard, _ := syscall.GetProcAddress(MAINDLL, "ReadCard")

r1, r2, errno := syscall.Syscall12(readCard,
    11,
    uintptr(unsafe.Pointer(&room)),
    uintptr(unsafe.Pointer(&gate)),
    uintptr(unsafe.Pointer(&stime)),
    uintptr(unsafe.Pointer(&guestname)),
    uintptr(unsafe.Pointer(&guestid)),
    uintptr(unsafe.Pointer(&lift)),
    uintptr(unsafe.Pointer(&track1)),
    uintptr(unsafe.Pointer(&track2)),
    uintptr(cardno),
    uintptr(st),
    uintptr(Breakfast),
    0)

fmt.Println(r1, "
", r2, "
", errno)`

when i run this code , i got

r1:0    r2:917452    errno:<nil>

but when i print room or other param , it's value doesn't change, this function in dll file will change the param i send , how can i got those value?

  • 写回答

1条回答 默认 最新

  • douzhao9608 2017-07-17 15:27
    关注

    To retrieve C's NULL terminated string, use pointer to pre-allocated byte slice instead of string. You need to make sure that the byte slice has enough space for storing the character, otherwise your program may crash due to memory access violation.

    For long * and int * type, address to the variable is needed, e.g. use uintptr(unsafe.Pointer(&cardno)) instead of uintptr(cardno). In your current implementation, the value pointed by the variable is converted to a pointer. All uintptr(cardno), uintptr(st), uintptr(Breakfast) point to the same pointer (pointer to NULL in C) since they're all initialized to 0.

    The code looks like:

    const maxSize = 100 //Adjust the value to your need
    
    room := make([]byte, maxSize)
    gate := make([]byte, maxSize)
    stime := make([]byte, maxSize)
    guestname := make([]byte, maxSize)
    guestid := make([]byte, maxSize)
    lift := make([]byte, maxSize)
    track1 := make([]byte, maxSize)
    track2 := make([]byte, maxSize)
    
    //The following variable type is correct for 64-bit DLL.
    //For 32-bit DLL, instead of int64, use int32.
    cardno := int64(0)
    st := int64(0)
    Breakfast := int64(0)
    
    MAINDLL, _ := syscall.LoadLibrary("xxxxx.dll")
    defer syscall.FreeLibrary(MAINDLL)
    readCard, _ := syscall.GetProcAddress(MAINDLL, "ReadCard")
    
    r1, r2, errno := syscall.Syscall12(readCard,
        11,
        uintptr(unsafe.Pointer(&room[0])),
        uintptr(unsafe.Pointer(&gate[0])),
        uintptr(unsafe.Pointer(&stime[0])),
        uintptr(unsafe.Pointer(&guestname[0])),
        uintptr(unsafe.Pointer(&guestid[0])),
        uintptr(unsafe.Pointer(&lift[0])),
        uintptr(unsafe.Pointer(&track1[0])),
        uintptr(unsafe.Pointer(&track2[0])),
        uintptr(unsafe.Pointer(&cardno)),
        uintptr(unsafe.Pointer(&st)),
        uintptr(unsafe.Pointer(&Breakfast)),
        0)
    
    fmt.Println(r1, "
    ", r2, "
    ", errno)
    

    Note that in the above example, we're using &room[0] intead of room, since we need to pass address of underlying byte array instead of address of the slice descriptor (See https://blog.golang.org/go-slices-usage-and-internals).

    Finally, the byte slice which holds NULL terminated string must be converted to go's string, e.g. using:

    func cstr(buf []byte) string {
        str := string(buf)
        for i, r := range str {
            if r == 0 {
                return string(buf[:i])
            }
        }
        return str
    }
    
    //usage example
    sRoom := cstr(room)
    //see the difference
    fmt.Printf("`%s` => `%s`
    ", string(room), sRoom)
    

    Other implementation example, see How can I convert a null-terminated string in a byte buffer to a string in Go?.

    评论

报告相同问题?

悬赏问题

  • ¥15 vue3加ant-design-vue无法渲染出页面
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏
  • ¥15 gg加速器加速游戏时,提示不是x86架构
  • ¥15 python按要求编写程序