C# [Out] [MarshalAs(..) to VB.NET

Viewed 1209

I'm converting a C# code to VB.NET, and the following line gives me a head ache:

    int GetChannelCount(
        [Out] [MarshalAs(UnmanagedType.U4)] out UInt32 channelCount);

The online converters don't know how to handle

[Out]

I understand "out" (that would be "ByRef"), but I don't know what "[Out]" does and how to convert that to VB.NET.

Thank you.

ps: This is the entire code if it's important:

http://netcoreaudio.codeplex.com/SourceControl/latest#trunk/Code/CoreAudio/Interfaces/IAudioEndpointVolume.cs

[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAudioEndpointVolume
{
    [PreserveSig]
    int NotImpl1();

    [PreserveSig]
    int NotImpl2();

    /// <summary>
    /// Gets a count of the channels in the audio stream.
    /// </summary>
    /// <param name="channelCount">The number of channels.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int GetChannelCount(
        [Out] [MarshalAs(UnmanagedType.U4)] out UInt32 channelCount);

    /// <summary>
    /// Sets the master volume level of the audio stream, in decibels.
    /// </summary>
    /// <param name="level">The new master volume level in decibels.</param>
    /// <param name="eventContext">A user context value that is passed to the notification callback.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int SetMasterVolumeLevel(
        [In] [MarshalAs(UnmanagedType.R4)] float level,
        [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

    /// <summary>
    /// Sets the master volume level, expressed as a normalized, audio-tapered value.
    /// </summary>
    /// <param name="level">The new master volume level expressed as a normalized value between 0.0 and 1.0.</param>
    /// <param name="eventContext">A user context value that is passed to the notification callback.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int SetMasterVolumeLevelScalar(
        [In] [MarshalAs(UnmanagedType.R4)] float level,
        [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

    /// <summary>
    /// Gets the master volume level of the audio stream, in decibels.
    /// </summary>
    /// <param name="level">The volume level in decibels.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int GetMasterVolumeLevel(
        [Out] [MarshalAs(UnmanagedType.R4)] out float level);

    /// <summary>
    /// Gets the master volume level, expressed as a normalized, audio-tapered value.
    /// </summary>
    /// <param name="level">The volume level expressed as a normalized value between 0.0 and 1.0.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int GetMasterVolumeLevelScalar(
        [Out] [MarshalAs(UnmanagedType.R4)] out float level);

    /// <summary>
    /// Sets the volume level, in decibels, of the specified channel of the audio stream.
    /// </summary>
    /// <param name="channelNumber">The channel number.</param>
    /// <param name="level">The new volume level in decibels.</param>
    /// <param name="eventContext">A user context value that is passed to the notification callback.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int SetChannelVolumeLevel(
        [In] [MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
        [In] [MarshalAs(UnmanagedType.R4)] float level,
        [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

    /// <summary>
    /// Sets the normalized, audio-tapered volume level of the specified channel in the audio stream.
    /// </summary>
    /// <param name="channelNumber">The channel number.</param>
    /// <param name="level">The new master volume level expressed as a normalized value between 0.0 and 1.0.</param>
    /// <param name="eventContext">A user context value that is passed to the notification callback.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int SetChannelVolumeLevelScalar(
        [In] [MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
        [In] [MarshalAs(UnmanagedType.R4)] float level,
        [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

    /// <summary>
    /// Gets the volume level, in decibels, of the specified channel in the audio stream.
    /// </summary>
    /// <param name="channelNumber">The zero-based channel number.</param>
    /// <param name="level">The volume level in decibels.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int GetChannelVolumeLevel(
        [In] [MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
        [Out] [MarshalAs(UnmanagedType.R4)] out float level);

    /// <summary>
    /// Gets the normalized, audio-tapered volume level of the specified channel of the audio stream.
    /// </summary>
    /// <param name="channelNumber">The zero-based channel number.</param>
    /// <param name="level">The volume level expressed as a normalized value between 0.0 and 1.0.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int GetChannelVolumeLevelScalar(
        [In] [MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
        [Out] [MarshalAs(UnmanagedType.R4)] out float level);

    /// <summary>
    /// Sets the muting state of the audio stream.
    /// </summary>
    /// <param name="isMuted">True to mute the stream, or false to unmute the stream.</param>
    /// <param name="eventContext">A user context value that is passed to the notification callback.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int SetMute(
        [In] [MarshalAs(UnmanagedType.Bool)] Boolean isMuted,
        [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

    /// <summary>
    /// Gets the muting state of the audio stream.
    /// </summary>
    /// <param name="isMuted">The muting state. True if the stream is muted, false otherwise.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int GetMute(
        [Out] [MarshalAs(UnmanagedType.Bool)] out Boolean isMuted);

    /// <summary>
    /// Gets information about the current step in the volume range.
    /// </summary>
    /// <param name="step">The current zero-based step index.</param>
    /// <param name="stepCount">The total number of steps in the volume range.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int GetVolumeStepInfo(
        [Out] [MarshalAs(UnmanagedType.U4)] out UInt32 step,
        [Out] [MarshalAs(UnmanagedType.U4)] out UInt32 stepCount);

    /// <summary>
    /// Increases the volume level by one step.
    /// </summary>
    /// <param name="eventContext">A user context value that is passed to the notification callback.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int VolumeStepUp(
        [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

    /// <summary>
    /// Decreases the volume level by one step.
    /// </summary>
    /// <param name="eventContext">A user context value that is passed to the notification callback.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int VolumeStepDown(
        [In] [MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);

    /// <summary>
    /// Queries the audio endpoint device for its hardware-supported functions.
    /// </summary>
    /// <param name="hardwareSupportMask">A hardware support mask that indicates the capabilities of the endpoint.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int QueryHardwareSupport(
        [Out] [MarshalAs(UnmanagedType.U4)] out UInt32 hardwareSupportMask);

    /// <summary>
    /// Gets the volume range of the audio stream, in decibels.
    /// </summary>
    /// <param name="volumeMin">The minimum volume level in decibels.</param>
    /// <param name="volumeMax">The maximum volume level in decibels.</param>
    /// <param name="volumeStep">The volume increment level in decibels.</param>
    /// <returns>An HRESULT code indicating whether the operation passed of failed.</returns>
    [PreserveSig]
    int GetVolumeRange(
        [Out] [MarshalAs(UnmanagedType.R4)] out float volumeMin,
        [Out] [MarshalAs(UnmanagedType.R4)] out float volumeMax,
        [Out] [MarshalAs(UnmanagedType.R4)] out float volumeStep);
}
1 Answers

out is a modifier that causes the parameter to be passed by ref without the need to be initialized first as is the case with ref in C#. It is meant to write a value to the parameter passed so the direction of modification is out of the called method. Consider the TryParse() methods in some of the .NET Framework types.

string foo = "123";
int value;
if(int.TryParse(foo, out value)) // Returns true if it can be parsed in which case, value now holds the parsed value
{
    // Do something
}

VB.NET does not have an equivalent for this because it initializes variables by default and you just call it ByRef as normal. In the context of using it with platform invoke as the code you posted is doing, you only need to call the Out attribute which has the same effect for platform invoke, by causing data to be marshalled from the called method to the calling method. Consider the following code:

<PreserveSig>
Function GetChannelCount(<Out, MarshalAs(UnmanagedType.U4)> ByRef channelCount As UInt32) As Integer

End Function

This essentially tells the runtime that the ByRef parameter you defined should be treated as an out parameter so to speak allowing the called method to write to it without needing it to be initialized first.

Related