簡體   English   中英

如何將IntPtr轉換為結構?

[英]How to get an IntPtr to a struct?

我有簽名的方法

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

Rect是一個結構體,但我還需要允許調用者將null (或IntPtr.Zero )也傳遞給該方法。

我想然后將其傳遞給具有簽名的DLL

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

我希望可以做以下事情:

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

但是我不能像這樣強制轉換結構。 我還有其他方法可以獲取IntPtr嗎?


替代方法是創建4個重載:

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

如果我需要傳遞兩個以上的struct指針,可能會變得更加混亂。


我想出了一個解決方案,但對此有一些疑問:

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;
}

如果使用ref Rect ,就不必為該結構分配內存了-這樣做有什么不同?


我做了一些實驗。 ref Rect解決方案的運行速度與 Rect轉換為IntPtr Rect生成IntPtr ,這使我懷疑使用ref時C#在后台執行的操作非常相似。 一旦我使它成Rect? 並將條件邏輯添加到運行速度降低50%的方法中...因此,4重載路徑可能是最快的。 但是,對於100K迭代,我們正在討論100-150ms,這意味着該方法本身非常便宜,這可能就是為什么條件產生如此顯着影響的原因。 因此,我堅持使用自定義的StructToPtr解決方案,因為它是最簡單的解決方案。

您想使用Marshal.StructureToPtr

您還必須為該結構分配和取消分配內存。

可以在http://www.developerfusion.com/article/84519/mastering-structs-in-c/中找到有關該主題的好博客

這就是我所擁有的,我正在使用M $ DLL中的API,原型如下所示:

HRESULT C_API(LPCWSTR name, PSTRUCT_WHATEVER *ppStruct);

結構定義如下:

typedef struct whatever {
    LPCWSTR x;
    LPCWSTR y;
}

在C#中,我定義了以下內容:

[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);

要使用它:

IntPtr s;           
long HR = C_API("myname", out s);

WHATEVER pInfo = (WHATEVER) Marshal.PtrToStructure(s, typeof(WHATEVER));

String mystring = Marshal.PtrToStringAuto(pInfo.x);

此時,mystring =“這是一個字符串”;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM