How to pass a pointer from C# to native function in DLL?

Viewed 13599

This is the signature of my function in DLL:

int __stdcall myFun( void * const context, const char * const pszFileName, const unsigned int buffSize, void * const pWaveFormatex );

All parameters are [in]. The user should pass a pointer to a WAVEFORMATEX struct through the last parameter. Upon return, it will be filled. All that works very well in C++.

Now, I'm trying for days to use the same DLL from C# and it simply doesn't work. The problem is in the last parameter. Since I do not know C# at all, I would like to ask somebody if this is doable at all. If it is, I would appreciate an example.

One of my last attempts was this:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WAVEFORMATEX
{
    public ushort wFormatTag;
    public ushort nChannels;
    public uint nSamplesPerSec;
    public uint nAvgBytesPerSec;
    public ushort nBlockAlign;
    public ushort wBitsPerSample;
    public ushort cbSize;
}

Note: I also built my DLL written in C++ with the Struct Member Alignment = 1. Maybe I'm stupid, but I thought that Pack = 1 above is related with that in C++, but I have no idea if it is...

[DllImport("myLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
        public static extern int myFun( IntPtr context,
                                        [MarshalAs( UnmanagedType.LPStr )]
                                        string pszFileName,
                                        int bufferSize,
                                        ref IntPtr pWfx );

IntPtr unmanaged_pWfx = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WAVEFORMATEX)));

result = DLLWrapper.myFun(context,
                          "C:\\video.wmv",
                          176400,
                          ref unmanaged_pWfx );

WAVEFORMATEX wfxFormat = (WAVEFORMATEX)Marshal.PtrToStructure( unmanaged_pWfx, typeof(WAVEFORMATEX));

The behavior is undefined. Sometimes it hangs, sometimes it terminates... Something is very wrong. However, the problem is not in the DLL, the problem is on the C# side. Is C# capable of working with pointers at all?

Thanks for any feedback you provide.

EDIT (working C++ code):

void * context;
WAVEFORMATEX wfx;
int success = getContext( &context );
success = myFun( context, "C:\\video.wmv", 176400, &wfx );

The equivalent in C# is:

IntPtr context;
WAVEFORMATEX wfx;

int success = getContext( out context );
success = myFun( context, "C:\\video.wmv", 176400, out wfx );


extern "C" __stdcall int getContext( void ** pContext );

[DllImport("myLib.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int getContext(out IntPtr context);
2 Answers
Related