1

I need your help.

I am trying to import a C Dll into a C# project. While doing that, I need pass a struct between the Dll and C# project in both directions.

Here is C definition:

struct mwBITMAP 
{
 int bmWidth;
 int bmHeight;
 BYTE* bmData;
}; 

Here is C# definition:

   [StructLayout(LayoutKind.Sequential)] 
    public struct MwRemoteBmp
    {
        public int Width;
        public int Height;
        public byte[] Data;
    }

I tried to pass the a struct (the Data is well initialized) from C# to a dll's test function by reference. The width and height are both right. But the Data is all wrong.

Where did I make mistakes?

2 Answers 2

3

Yes, the array gets marshaled as a SAFEARRAY. Not crashing the pinvoke marshaller is pretty unusual. Declare the Data member as IntPtr, then use Marshal.Copy() to copy the data.

Beware that this would be hard to use in C as well. There's a memory management problem, it isn't clear who owns the array. Most typically, the C function would use malloc() to allocate the array. That's a big problem, you cannot release that array in C#, no way to call free(). You'll have an unpluggable memory leak. If you can't rewrite the C code then you'll need to write a wrapper in the C++/CLI language so that you can call free(). Even that is tricky if the C dll doesn't use the same CRT as the C++/CLI code. You have to compile the C code with the /MD option.

Sign up to request clarification or add additional context in comments.

4 Comments

If I allocate memory for the Data member only in C# and pass the struct to C to modify Data's value. And call Marshal.FreeHGlobal in C# to free the memory after it's done. Will that be OK?
Yes, as long as you modify Data's content, not value. You however won't know how much memory to allocate until you know the size of the bitmap. Short from using the SAFEARRAY api, you could fix the problem in C by calling GlobalAlloc so you can use Marshal.FreeHGlobal in C#.
Fortunately both C and C# parts are implemented by myself so I can gain more control over it. Is there any better way to do this?
The approaches I gave in the previous comment will work. You could also add a ReleaseBitmap export. Other than that, lose the struct and replace with 3 functions.
2

Use the IntPtr type instead of byte[] type. In your example:

[StructLayout(LayoutKind.Sequential)] 
public struct MwRemoteBmp
{
    public int Width;
    public int Height;
    public IntPtr Data;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.