简体   繁体   中英

PInvoke not working in class definition

I have a problem, strange one. When I am using with the next struct in PInvoke it is working but when I change it to class it is not working.

my c# :

[StructLayout(LayoutKind.Sequential)]
public struct SPInvokeImage
{          
    public int m_BitsPerPixel;  // 8,16,24,32 
    public int m_ImageHeight;
    public int m_ImageWidth;
    public int m_BytesArraySize; // array size in bytes. 

    public IntPtr m_pArray; //data array 
}

c++

   typedef struct 
   {          
 int mBitsPerPixel;  // 8,16,24,32 
 int mImageHeight;
 int mImageWidth;
 int BytesArraySize; // array size in bytes. 

 uint8_t *Array;        //data array 
   }SPInvokeImage;

when I change the c# to be like this it stops working:

 [StructLayout(LayoutKind.Sequential)]
 public class SPInvokeImage
 {          
     public int m_BitsPerPixel;  // 8,16,24,32 
     public int m_ImageHeight;
     public int m_ImageWidth;
     public int m_BytesArraySize; // array size in bytes. 

     public IntPtr m_pArray; //data array 
 }

It's because when you switch to a class, the object is passed to the native code by reference rather than by value as it is for a struct . So there is an extra level of indirection. You'll need to remove that level of indirection in your pinvoke declaration. You are probably passing using ref at the moment. Simply remove the ref when you switch from struct to class .

Structs are value types, while classes are reference types. The rules for how those two types are passed into a P/Invoke method call are different.

Is there a particular reason you want to use a class when a struct is working fine? You clearly want value-type semantics, so use a value type to get them.

If you truly need to make it a class for some reason, I'd need to see the method signature you're calling to see what is going wrong. Most likely you have a ref tacked on somewhere it doesn't belong.

EDIT: Based on your comment about null pointers:

Using a class here is one option, just make sure you don't pass it explicitly by ref , since that happens automatically. Another option is to use an IntPtr and pass either IntPtr.Zero for a null value, or the result of Marshal.StructureToPtr for a real value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM