如何在自定义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?

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