Search code examples
c#c++pointersinteropservices

Preserve C++ Pointer in C#


I am writing a little Program in C# which includes a C++ Dll.

In C++, there are many classes which needed to be instanced and left for later use. This looks like the following function:

C++:
__declspec(dllexport) FrameCapture* GetFrameCapturer(HWND windowHandle) {
    ProcessWindow* window = ProcessWindowCollection::GetInstance()->FindWindow(windowHandle);
    FrameCapture* capture = new FrameCapture(window);
    return capture;
}

As you can see I just create a FrameCapture class and return a Pointer to it.

This Pointer is stored in C# as an IntPtr.

C#:
[DllImport("<dllnamehere>")]
public static extern IntPtr GetFrameCapturer(IntPtr windowHandle);

This works really well so far. But if I use that Pointer to get an Instance of FrameCapture

C++:
__declspec(dllexport) BITMAPFILEHEADER* GetBitmapFileHeader(FrameCapture* frameCapturer) {
    return frameCapturer->GetBitmapFileHeader();
}

the class will be completely empty. How do I get the Instance of the Class I initialized in step one?

EDIT:

I did some testing and replaced the Pointers with integers which are better to look at.

I casted 'capture' to an Int32 and returned this instead. In my testcase it returned byte(208,113,244,194). This values are, as expected, in C++ and C# the same.

But, now it becomes odd.

If I pass this Int32 into 'GetBitmapFileHeader' the value becomes suddenly byte(184,231,223,55).

That's not even close! I thought of Little <-> Big Endian or something like this but, this is a whole new Memoryblock?

The same behavior will go on with the IntPtr.

As requested I post also the Import of 'GetBitmapFileHeader'

[DllImport("<dllnamehere>")]
public static extern tagBITMAPFILEHEADER GetBitmapFileHeader(IntPtr capturerHandle);

Solution

  • Okay, I got it.

    See this import from C#.

    C#:
    [DllImport("<dllnamehere>")]
    public static extern tagBITMAPFILEHEADER GetBitmapFileHeader(IntPtr capturerHandle);
    

    Its wrong!

    The function now returns an IntPtr wich works completely fine.

    This is the new Setup:

    C++:

        __declspec(dllexport) void* __stdcall GetBitmapFileHeader(void* frameCapturer) {
    
            FrameCapture* cap = (FrameCapture*)frameCapturer;
            return cap->GetBitmapFileHeader();
        }
    

    C#:

    [DllImport("libWinCap.dll", CallingConvention = CallingConvention.StdCall)]
    public static extern IntPtr GetBitmapFileHeader(IntPtr frameCapturer);
    
    [...]
    //calling
    IntPtr ptr = GetBitmapFileHeader(m_capturerHandle);
    m_bitmap.m_fileHeader = (tagBITMAPFILEHEADER)Marshal.PtrToStructure(ptr, typeof(tagBITMAPFILEHEADER));
    

    Iam only moving Pointers now and use PtrToStructure to read the Memory.

    Also, Thanks for every comment.