How to get IntPtr for a structure?

I have a method with a signature

public int Copy(Texture texture, Rect? srcrect, Rect? dstrect) 

Rect is a structure, but I need to allow the caller to pass a null (or IntPtr.Zero ) method.

I want to pass it to a signed DLL

 [DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_RenderCopy")] internal static extern int RenderCopy(IntPtr renderer, IntPtr texture, IntPtr srcrect, IntPtr dstrect); 

I was hoping I could do something like the following:

 return SDL.RenderCopy(_ptr, texture._ptr, srcrect.HasValue ? (IntPtr)srcrect.Value : IntPtr.Zero, dstrect.HasValue ? (IntPtr)dstrect.Value : IntPtr.Zero); 

But I can not use such a structure. Is there any other way to get IntPtr from this?


An alternative would be to create 4 overloads:

  • ref Rect, ref Rect
  • IntPtr, IntPtr
  • ref Rect, IntPtr
  • IntPtr, ref Rect

which can become even more messy if I ever need to pass in more than two pointers to a structure.


I came up with a solution, but I have some questions about this:

 public int Copy(Texture texture, Rect? srcrect=null, Rect? dstrect=null) { return SDL.RenderCopy(_ptr, texture._ptr, srcrect.HasValue ? StructToPtr(srcrect) : IntPtr.Zero, dstrect.HasValue ? StructToPtr(dstrect) : IntPtr.Zero); } private static IntPtr StructToPtr(object obj) { var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj)); Marshal.StructureToPtr(obj, ptr, false); return ptr; } 

If I used ref Rect , I would not have to allocate memory for the structure - what does it do differently than it does?


I experimented a bit. The ref Rect solution runs at about the same speed as converting a Rect to IntPtr by generating IntPtr for Rect , which makes me suspect that C # is doing something very similar under the hood when you use refs. As soon as I do this Rect? and add conditional logic to the method, it will work 50% slower ... so the 4-overload route will probably be the fastest. Nevertheless, we are talking about 100-150 ms for iterations of 100 KK, which means that the method itself is super cheap, and this is probably why conventions have such a noticeable effect. Thus, I stick with my custom StructToPtr solution, as this is the simplest solution.

+6
source share
2 answers

You want to use Marshal.StructureToPtr .

You will also have to allocate and free memory for the structure.

A good blog on this topic can be found at http://www.developerfusion.com/article/84519/mastering-structs-in-c/

+7
source

Here is what I have, I use the API from the M $ DLL, and the prototype looks like this:

 HRESULT C_API(LPCWSTR name, PSTRUCT_WHATEVER *ppStruct); 

The structure is defined as such:

 typedef struct whatever { LPCWSTR x; LPCWSTR y; } 

In C #, I define the following:

 [StructLayout(LayoutKind.Sequential)] public class WHATEVER { public IntPtr x; public IntPtr y; } [DllImport("msdll.dll", SetLastError=false, CharSet=CharSet.Unicode)] public static extern long C_API(String name, out IntPtr ppStruct); 

To use it:

 IntPtr s; long HR = C_API("myname", out s); WHATEVER pInfo = (WHATEVER) Marshal.PtrToStructure(s, typeof(WHATEVER)); String mystring = Marshal.PtrToStringAuto(pInfo.x); 

At this moment mystring = "this is a string";

-2
source

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


All Articles