Problem using a fixed length string in a structure used as a parameter to a Win32API call
-
Imports System.Runtime.InteropServices Public Class Form1 Public Const MAXPNAMELEN = 32 ' max product name length (including NULL) _ Structure MIDIINCAPS 'Structure def copied from win32api.txt Dim wMid As Int16 Dim wPid As Int16 Dim vVersion As Integer _ Dim szPname As String 'win32api.txt def is String*MAXPNAMELEN End Structure Declare Function midiInGetNumDevs Lib "winmm.dll" () As Long Declare Function midiInGetDevCaps Lib "winmm.dll" Alias "midiInGetDevCapsA" _ (ByVal uDeviceID As Int32, ByVal lpCaps As MIDIINCAPS, ByVal uSize As Int32) As Int32 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim retval As Int32 Dim NumMidiInDevices As Int32 Dim DevCounter As Int32 Dim devicecaps As New MIDIINCAPS NumMidiInDevices = midiInGetNumDevs() For DevCounter = 0 To NumMidiInDevices - 1 retval = midiInGetDevCaps(DevCounter, devicecaps, Len(devicecaps)) ' Runtime error msg here '======================================================================= 'A call to PInvoke function 'MidiInCapTest!MidiInCapTest.Form1::midiInGetDevCaps' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature. '======================================================================== Next DevCounter End Sub '============================================================================ 'I have tried instead of Marshall as, in the sructure plus countless tries at int16, int32 etc for the other parameters in the API call,in a fruitless attempt to outwit the known inconsistencies between winapi32.txt data types & .NET but to no avail. 'Can anyone help End Class
-
Imports System.Runtime.InteropServices Public Class Form1 Public Const MAXPNAMELEN = 32 ' max product name length (including NULL) _ Structure MIDIINCAPS 'Structure def copied from win32api.txt Dim wMid As Int16 Dim wPid As Int16 Dim vVersion As Integer _ Dim szPname As String 'win32api.txt def is String*MAXPNAMELEN End Structure Declare Function midiInGetNumDevs Lib "winmm.dll" () As Long Declare Function midiInGetDevCaps Lib "winmm.dll" Alias "midiInGetDevCapsA" _ (ByVal uDeviceID As Int32, ByVal lpCaps As MIDIINCAPS, ByVal uSize As Int32) As Int32 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim retval As Int32 Dim NumMidiInDevices As Int32 Dim DevCounter As Int32 Dim devicecaps As New MIDIINCAPS NumMidiInDevices = midiInGetNumDevs() For DevCounter = 0 To NumMidiInDevices - 1 retval = midiInGetDevCaps(DevCounter, devicecaps, Len(devicecaps)) ' Runtime error msg here '======================================================================= 'A call to PInvoke function 'MidiInCapTest!MidiInCapTest.Form1::midiInGetDevCaps' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature. '======================================================================== Next DevCounter End Sub '============================================================================ 'I have tried instead of Marshall as, in the sructure plus countless tries at int16, int32 etc for the other parameters in the API call,in a fruitless attempt to outwit the known inconsistencies between winapi32.txt data types & .NET but to no avail. 'Can anyone help End Class
The main thing is that the 2nd parameter should be 'ByRef':
Declare Function midiInGetDevCaps Lib "winmm.dll" Alias "midiInGetDevCapsA" (ByVal uDeviceID As Integer, ByRef lpCaps As MIDIINCAPS, ByVal uSize As Integer) As Integer
Public Structure MIDIINCAPS
Dim ManufacturerID As Short
Dim ProductID As Short
Dim DriverVersion As Integer
Dim Label As String
Dim Support As Integer
End StructureDavid Anton Convert between VB, C#, C++, & Java www.tangiblesoftwaresolutions.com
-
Imports System.Runtime.InteropServices Public Class Form1 Public Const MAXPNAMELEN = 32 ' max product name length (including NULL) _ Structure MIDIINCAPS 'Structure def copied from win32api.txt Dim wMid As Int16 Dim wPid As Int16 Dim vVersion As Integer _ Dim szPname As String 'win32api.txt def is String*MAXPNAMELEN End Structure Declare Function midiInGetNumDevs Lib "winmm.dll" () As Long Declare Function midiInGetDevCaps Lib "winmm.dll" Alias "midiInGetDevCapsA" _ (ByVal uDeviceID As Int32, ByVal lpCaps As MIDIINCAPS, ByVal uSize As Int32) As Int32 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim retval As Int32 Dim NumMidiInDevices As Int32 Dim DevCounter As Int32 Dim devicecaps As New MIDIINCAPS NumMidiInDevices = midiInGetNumDevs() For DevCounter = 0 To NumMidiInDevices - 1 retval = midiInGetDevCaps(DevCounter, devicecaps, Len(devicecaps)) ' Runtime error msg here '======================================================================= 'A call to PInvoke function 'MidiInCapTest!MidiInCapTest.Form1::midiInGetDevCaps' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature. '======================================================================== Next DevCounter End Sub '============================================================================ 'I have tried instead of Marshall as, in the sructure plus countless tries at int16, int32 etc for the other parameters in the API call,in a fruitless attempt to outwit the known inconsistencies between winapi32.txt data types & .NET but to no avail. 'Can anyone help End Class
Hi, This article[^] of mine should help you out for most issues. Yes it may take some experimenting; however for optimum progress, you should fix issues in this order: 1. The stack problem should be solved through the
CallingConvention
attribute. 2. The numeric parameters or fields should pose no problem, just make sure you use the managed/unmanaged types with matching sizes. 3. The fixed-length string field takes aMarshalAs
withSizeConst
(not sure a symbolic constant is acceptable); I expectByValTStr
is right, the doc says: Used for in-line, fixed-length character arrays that appear within a structure. The character type used with ByValTStr is determined by the System.Runtime.InteropServices.CharSet argument of the System.Runtime.InteropServices.StructLayoutAttribute applied to the containing structure. Good luck :)Luc Pattyn [My Articles] Nil Volentibus Arduum
-
The main thing is that the 2nd parameter should be 'ByRef':
Declare Function midiInGetDevCaps Lib "winmm.dll" Alias "midiInGetDevCapsA" (ByVal uDeviceID As Integer, ByRef lpCaps As MIDIINCAPS, ByVal uSize As Integer) As Integer
Public Structure MIDIINCAPS
Dim ManufacturerID As Short
Dim ProductID As Short
Dim DriverVersion As Integer
Dim Label As String
Dim Support As Integer
End StructureDavid Anton Convert between VB, C#, C++, & Java www.tangiblesoftwaresolutions.com
-
Hi, This article[^] of mine should help you out for most issues. Yes it may take some experimenting; however for optimum progress, you should fix issues in this order: 1. The stack problem should be solved through the
CallingConvention
attribute. 2. The numeric parameters or fields should pose no problem, just make sure you use the managed/unmanaged types with matching sizes. 3. The fixed-length string field takes aMarshalAs
withSizeConst
(not sure a symbolic constant is acceptable); I expectByValTStr
is right, the doc says: Used for in-line, fixed-length character arrays that appear within a structure. The character type used with ByValTStr is determined by the System.Runtime.InteropServices.CharSet argument of the System.Runtime.InteropServices.StructLayoutAttribute applied to the containing structure. Good luck :)Luc Pattyn [My Articles] Nil Volentibus Arduum
See my reply to David Anton's ByRef suggestio which was the only change I made. Thanks for the link to your article which also mentions delegates. Now that Phase one (identify connected MIDI devices) works I shall code the MidiIn phase....watch this space!