Question

I have the following interface method declaration in C#:

[ComVisible(true), ComImport, SuppressUnmanagedCodeSecurity,
Guid("A668B8F2-BA87-4F63-9D41-768F7DE9C50E"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ILAVAudioStatus
{
    [PreserveSig]
    int GetOutputDetails(out IntPtr pOutputFormat, out int pnChannels, out int pSampleRate, out uint pChannelMask);
}

pOutputformat is actually a char** in C++

I need to do a Marshal.PtrToStringAnsi(pOutputformat) to get the actual string.

Is there some marshalling attribute that can convert pOutputformat directly to an out string instead of using an IntPtr?

This is what the C++ method does:

HRESULT CLAVAudio::GetOutputDetails(const char **pOutputFormat, int *pnChannels, int *pSampleRate, DWORD *pChannelMask)
{
  if(!m_pOutput || m_pOutput->IsConnected() == FALSE) {
    return E_UNEXPECTED;
  }
  if (m_avBSContext) {
    if (pOutputFormat) {
      *pOutputFormat = get_sample_format_desc(SampleFormat_Bitstream);
    }
    return S_FALSE;
  }
  if (pOutputFormat) {
    *pOutputFormat = get_sample_format_desc(m_OutputQueue.sfFormat);
  }
  if (pnChannels) {
    *pnChannels = m_OutputQueue.wChannels;
  }
  if (pSampleRate) {
    *pSampleRate = m_OutputQueue.dwSamplesPerSec;
  }
  if (pChannelMask) {
    *pChannelMask = m_OutputQueue.dwChannelMask;
  }
  return S_OK;
}
Was it helpful?

Solution

Marshal.PtrToStringAnsi(pOutputformat)

is the best that you can do. There's no avoiding that. If you try to marshal as out string OutputFormat then the marshaller will call CoTaskMemFree on the pointer returned by the native code. And that ends in tears.

The question remains as to who is responsible for deallocating the memory that pOutputformat points to? Only you can know the answer to that.

One wonders why the designer of this COM interface chose to use C strings rather than the COM BSTR.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top