Tableau de structures dans de la mémoire non-managé

Signaler
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
-
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
-
Bonjour,

Je suis en train de faire un Wrapper de l'API Mixer en VB.NET. Je n'ai pas eu de problèmes particuliers jusqu'à ce que je sois apparement obligé de passer par de la mémoire non managé.

Il s'agit de la fonction 'mixerGetLineControls' qui à une structure MIXERLINECONTROLS comme paramètre. Dans certains cas, on doit créer un tableau de structures MIXERCONTROL et définir le pointeur de la 1ère structure du tableau à l'un des membres de MIXERLINECONTROLS:
"The pmxlc parameter references a list of MIXERCONTROL structures that will receive information on all controls associated with the audio line identified by the dwLineID member of the MIXERLINECONTROLS structure. The cControls member must be initialized to the number of controls associated with the line. ..... The cbmxctrl member must be initialized to the size, in bytes, of a single MIXERCONTROL structure. The pamxctrl member must point to the first MIXERCONTROL structure to be filled."

Référence MSDN de mixerGetLineControls

Dans certains cas, il ne faut pas créer un tableau de MIXERCONTROL, mais une seule structure MIXERCONTROL: "The pamxctrl member must point to a MIXERCONTROL structure to be filled"
Et ça, j'ai réussis à le faire et ça fonctionne:

      Dim errorCode As Integer    ' Code d'erreur lors de l'appel d'une fonction de l'API
        Dim hMixer As IntPtr        ' Handle de l'objet Mixer

        ' Ouverture du Mixer (retour handle, Numéro du device, handle callback, tjrs 0, flag)
        errorCode = mixerOpen(hMixer, 0, Nothing, 0, 0)

        ' Création d'une structure MixerControl pour récupérer les infos d'un control
        Dim mixerControl As New MIXERCONTROL
        mixerControl.cbStruct = Marshal.SizeOf(mixerControl)        ' Taille de la structure
        Dim pmem As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(mixerControl))   ' Allocation de mémoire non-managé

        ' Création d'une strucure MixerLineControls pour l'appel de l'API
        Dim mixerLineControls As New MIXERLINECONTROLS
        mixerLineControls.cbStruct = Marshal.SizeOf(mixerLineControls) ' Taille de la structure
        mixerLineControls.dwLineID = &HFFFF0000     ' ID de la ligne (= sortie WaveOut)
        mixerLineControls.dwControl = 1342373889    ' ID du control (= Volume)
        mixerLineControls.cControls = 0             ' Doit etre a 0 dans notre cas
        mixerLineControls.pamxctrl = pmem           ' Structure MixerControl pour le retour des infos
        mixerLineControls.cbmxctrl = Marshal.SizeOf(mixerControl)   ' Taille de la structure MixerControl

        ' Récupérer les infos de ce control (Handle du Mixer, structure MixerLineControls, flag (2=
ONEBYTYPE))
        errorCode = mixerGetLineControls(hMixer, mixerLineControls, 2)

        ' Récupérer la structure mixerControl à partir de la mémoire non-managé
        mixerControl = CType(Marshal.PtrToStructure(mixerLineControls.pamxctrl, GetType(MIXERCONTROL)), MIXERCONTROL)
        Marshal.FreeHGlobal(pmem) ' Libérer la mémoire non-managé

        ' Fermer le mixer
        errorCode = mixerClose(hMixer)

        ' Afficher les infos de la ligne
        Console.WriteLine("Nom         : " & mixerControl.szName)
        Console.WriteLine("Valeur min  : " & mixerControl.lMinimum)
        Console.WriteLine("Valeur max  : " & mixerControl.lMaximum)

Mais lorsque je dois passer un tableau, rien a faire, je n'y arrive pas et je ne trouve rien qui puisse m'aider.

Ceci ne semble pas fonctionner (Erreur = One or more parameters are invalid)

        Dim mixerControls() As MIXERCONTROL
        Dim pmem As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(mixerControls))
       ...
       mixerLineControls.pamxctrl = pmem

Quelqu'un aurait-il une sugestion?

1 réponse

Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
9
J'ai oublié de vous mettre les déclarations, si vous voulez faire tourner le code ça vous facilitera grandement la vie :)

Voici le code (de test) complet:

Imports System.Runtime.InteropServices

Public Class Form1

    ' Déclarations

    Friend Declare Function mixerGetLineControls Lib "winmm.dll" Alias "mixerGetLineControlsA" (ByVal hmxobj As Int32, ByRef pmxlc As MIXERLINECONTROLS, ByVal fdwControls As Int32) As Int32
    Friend Declare Function mixerOpen Lib "winmm.dll" (ByRef phmx As Int32, ByVal uMxId As Int32, ByVal dwCallback As Int32, ByVal dwInstance As Int32, ByVal fdwOpen As Int32) As Int32
    Friend Declare Function mixerClose Lib "winmm.dll" (ByVal hmx As Int32) As Int32

    <StructLayout(LayoutKind.Sequential)> _
Friend Structure MIXERCONTROL
       Public cbStruct As Integer
        Public dwControlID As Integer
        Public dwControlType As Integer
        Public fdwControl As Integer
        Public cMultipleItems As Integer
        <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=16)> Public szShortName As String
        <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=64)> Public szName As String
        Public lMinimum As Integer
        Public lMaximum As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11, ArraySubType:=UnmanagedType.AsAny)> Public reserved() As Integer
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
Friend Structure MIXERLINECONTROLS
       Public cbStruct As Integer
        Public dwLineID As Integer
        Public dwControl As Integer
        Public cControls As Integer
        Public cbmxctrl As Integer
        Public pamxctrl As IntPtr
    End Structure

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim errorCode As Integer    ' Code d'erreur lors de l'appel d'une fonction externe
        Dim hMixer As IntPtr        ' Handle de l'objet Mixer

        ' Ouverture du Mixer (retour handle, Numéro du device, handle callback, tjrs 0, flag)
        errorCode = mixerOpen(hMixer, 0, Nothing, 0, 0)

        ' Création d'une structure MixerControl pour récupérer les infos d'un control
        Dim mixerControl As New MIXERCONTROL
        mixerControl.cbStruct = Marshal.SizeOf(mixerControl)        ' Taille de la structure
        Dim pmem As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(mixerControl))   ' Allocation de mémoire non-managé

        ' Création d'une strucure MixerLineControls pour l'appel de l'API
        Dim mixerLineControls As New MIXERLINECONTROLS
        mixerLineControls.cbStruct = Marshal.SizeOf(mixerLineControls) ' Taille de la structure
        mixerLineControls.dwLineID = &HFFFF0000     ' ID de la ligne (= sortie WaveOut)
        mixerLineControls.dwControl = 1342373889    ' ID du control (= Volume)
        mixerLineControls.cControls = 0             ' Doit etre a 0
        mixerLineControls.pamxctrl = pmem           ' Structure MixerControl pour le retour des infos
        mixerLineControls.cbmxctrl = Marshal.SizeOf(mixerControl)   ' Taille de la structure MixerControl

        ' Récupérer les infos de ce control
        errorCode = mixerGetLineControls(hMixer, mixerLineControls, 2)

        ' Récupérer la structure mixerControl à partir de la mémoire non-managé
        mixerControl = CType(Marshal.PtrToStructure(mixerLineControls.pamxctrl, GetType(MIXERCONTROL)), MIXERCONTROL)
        Marshal.FreeHGlobal(pmem) ' Libérer la mémoire non-managé

        ' Fermer le mixer
        errorCode = mixerClose(hMixer)

        ' Afficher les infos de la ligne
        Console.WriteLine("Nom         : " & mixerControl.szName)
        Console.WriteLine("Valeur min  : " & mixerControl.lMinimum)
        Console.WriteLine("Valeur max  : " & mixerControl.lMaximum)
    End Sub
End Class