VB.Net为什么我的marshaled结构在传递ByVal时更新,但在传递ByRef时没有更新

时间:2014-04-14 08:14:49

标签: .net structure marshalling pass-by-reference pass-by-value

我一直在努力争取一些系统dll才能工作。我终于想出了如何让它发挥作用,但我不明白为什么。

我需要将结构传递给库函数midiOutPrepareHeader,并且该结构包含指向我分配的缓冲区的指针以及库设置的一些标志。在声明中我最初有 ByRef lpMidiOutHdr As IntPtr。没有明显的错误,但是下面的函数调用总是报告缓冲区还没有准备好" (准备好的旗帜没有设定)。当我最终将其更改为 ByVal lpMidiOutHdr As IntPtr时,调用后的结构副本设置了标志并且后续功能正常工作。

(我已经删除了用于检查结构的代码并找出发生了什么,但基本上这使用了PtrToStructure来解释数据,因此我可以检查它。< / p>

Private Declare Function fmidiOutPrepareHeader Lib "winmm.dll" Alias "midiOutPrepareHeader" (ByVal hMidiOut As Integer, ByVal lpMidiOutHdr As IntPtr, ByVal uSize As Integer) As Integer
Private Declare Function fmidiOutUnprepareHeader Lib "winmm.dll" Alias "midiOutUnprepareHeader" (ByVal hMidiOut As Integer, ByVal lpMidiOutHdr As IntPtr, ByVal uSize As Integer) As Integer
Private Declare Function fmidiOutLongMsg Lib "winmm.dll" Alias "midiOutLongMsg" (ByVal hMidiOut As Integer, ByVal lpMidiOutHdr As IntPtr, ByVal uSize As Integer) As Integer

Public Function midiOutGetDevCaps(ByVal uDeviceID As Integer, ByRef lpCaps As MIDIOUTCAPS) As Integer
    Return fmidiOutGetDevCaps(uDeviceID, lpCaps, Marshal.SizeOf(lpCaps))
End Function

Public Function midiOutLongMsg(ByVal hMidiOut As Integer, ByRef MidiOutHdr As MIDIHDR, ByRef MidiOutData As Byte()) As Integer
    Dim result As Integer
    MidiOutHdr.lpData = Marshal.AllocHGlobal(MidiOutHdr.dwBufferLength)     'allocate unmanaged memory for the data to be copied into. Set the header to point to it
    Marshal.Copy(MidiOutData, 0, MidiOutHdr.lpData, MidiOutHdr.dwBytesRecorded)
    Dim unmanagedHeader As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(MidiOutHdr))
    Marshal.StructureToPtr(MidiOutHdr, unmanagedHeader, True)
    result = fmidiOutPrepareHeader(hMidiOut, unmanagedHeader, Marshal.SizeOf(MidiOutHdr))
    result = fmidiOutLongMsg(hMidiOut, unmanagedHeader, Marshal.SizeOf(MidiOutHdr))
    result = fmidiOutUnprepareHeader(hMidiOut, unmanagedHeader, Marshal.SizeOf(MidiOutHdr))
    Marshal.FreeHGlobal(unmanagedHeader)
    Marshal.FreeHGlobal(MidiOutHdr.lpData)
    MidiOutHdr.lpData = 0
    Return result
End Function

任何人都可以解释为什么我在传递值时从数据库中获取数据,但是在通过引用传递时却没有?

非常感谢。 阿德里安

1 个答案:

答案 0 :(得分:0)

midiOutPrepareHeader方法的第二个参数是&#34;指向MIDIHDR结构的指针,用于标识要准备的缓冲区&#34;。你的IntPtr就是那个指针。通过声明参数ByRef,您传递的指针指向指针,而不是传递指针本身。