Unable to declare a pointer to an unmanaged type

I am trying to learn how to write a wrapper around a DLL, and I hit a little road block. I have a structure declared as such:

[StructLayout(LayoutKind.Sequential)] unsafe struct SDL_Surface { public readonly UInt32 flags; public readonly SDL_PixelFormat* format; public readonly int w, h; public readonly int pitch; public void* pixels; /// <summary>Application data associated with the surface</summary> public void* userdata; /// <summary>information needed for surfaces requiring locks</summary> public readonly int locked; public readonly void* lock_data; /// <summary>clipping information</summary> public readonly SDL_Rect clip_rect; /// <summary>info for fast blit mapping to other surfaces</summary> private SDL_BlitMap *map; // <--- Cannot take the address of, get the size of, or declare a pointer to a managed type /// <summary>Reference count -- used when freeing surface</summary> public int refcount; } 

When I try to compile my project, it gives the above error.

But you will notice above, I have a pointer to another structure. I am trying to understand what is the difference between these two structures, which does one job and the other does not, but I'm not sure; they are both unsafe structures. They look like this:

 [StructLayout(LayoutKind.Sequential)] unsafe struct SDL_PixelFormat { UInt32 format; SDL_Palette *palette; byte BitsPerPixel; byte BytesPerPixel; fixed byte padding [2]; UInt32 Rmask; UInt32 Gmask; UInt32 Bmask; UInt32 Amask; byte Rloss; byte Gloss; byte Bloss; byte Aloss; byte Rshift; byte Gshift; byte Bshift; byte Ashift; int refcount; SDL_PixelFormat *next; } unsafe internal delegate int SDL_blit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect); [StructLayout(LayoutKind.Sequential)] unsafe struct SDL_BlitMap { SDL_Surface* dst; int identity; SDL_blit blit; void* data; SDL_BlitInfo info; /* the version count matches the destination; mismatch indicates an invalid mapping */ UInt32 dst_palette_version; UInt32 src_palette_version; } [StructLayout(LayoutKind.Sequential)] struct SDL_Rect { int x, y; int w, h; } 

So what do I need to change to do this compilation?


I find the link to SDL_blit in SDL_BlitMap to be causing the problem. I declared this a delegate; is there anything else i should declare it? It is defined like this, in C:

 typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect, struct SDL_Surface * dst, SDL_Rect * dstrect); 
+4
source share
2 answers

Any structure containing a managed type cannot have its own address. Delegates are a reference type, so they are also managed. This means that SDL_Blitmap is a managed type because it contains a managed link to SDL_blit, so you cannot get a pointer to it without first fixing it.

If the function you are trying to call is already available in the dll, I suggest you take a look at the DllImportAttribute. ( http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.100).aspx )

By combining the extern public static declaration with DllImportAttribute, you can call any global function declared in the DLL that you intercept.

Alternatively, you will need to create a side C / C ++ function that takes a pointer to a function and calls it, which can become messy.

+5
source

What if you do not rely on insecure code? This can affect performance, even if your code has critical performance / speed. Something like that:

 [StructLayout(LayoutKind.Sequential)] struct SDL_PixelFormat { UInt32 format; IntPtr palettePtr; byte BitsPerPixel; byte BytesPerPixel; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] byte padding[]; UInt32 Rmask; UInt32 Gmask; UInt32 Bmask; UInt32 Amask; byte Rloss; byte Gloss; byte Bloss; byte Aloss; byte Rshift; byte Gshift; byte Bshift; byte Ashift; int refcount; IntPtr nextPtr; } [StructLayout(LayoutKind.Sequential)] struct SDL_Surface { public readonly UInt32 flags; public readonly IntPtr format; public readonly int w, h; public readonly int pitch; public IntPtr pixels; /// <summary>Application data associated with the surface</summary> public IntPtr userdata; /// <summary>information needed for surfaces requiring locks</summary> public readonly int locked; public readonly IntPtr lock_data; /// <summary>clipping information</summary> public readonly SDL_Rect clip_rect; /// <summary>info for fast blit mapping to other surfaces</summary> private IntPtr mapPtr; /// <summary>Reference count -- used when freeing surface</summary> public int refcount; } [StructLayout(LayoutKind.Sequential)] struct SDL_BlitMap { IntPtr dstPtr; int identity; SDL_blit blit; IntPtr data; SDL_BlitInfo info; /* the version count matches the destination; mismatch indicates an invalid mapping */ UInt32 dst_palette_version; UInt32 src_palette_version; } [StructLayout(LayoutKind.Sequential)] struct SDL_Rect { int x, y; int w, h; } [UnmanagedFunctionPointer(CallingConvention.ToBeAdded)] internal delegate int SDL_blit(ref SDL_Surface src, ref SDL_Rect srcrect, ref SDL_Surface dst, ref SDL_Rect dstrect); 

When you need to read any pointers to a structure:

 var palette = (SDL_Palette) Marshal.PtrToStructure(surface.palettePtr, typeof (SDL_Pallete)); 

Otherwise, if you want to stick with the current code, try declaring the function pointer as IntPtr instead of a delegate and create a delegate at run time using Marshal.GetDelegateForFunctionPointer.

+2
source

Source: https://habr.com/ru/post/1490206/


All Articles