2013-07-08 96 views
4

我正试图学习如何编写一个DLL包装器,并且我碰到了一点障碍。我有这样一个结构声明:不能声明指向非非托管类型的指针

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

当我尝试编译我的项目,它给出了上述错误。

但你会注意到它上面,我有一个指向另一个结构的指针。我试图弄清楚这两个结构之间的区别是什么使一个工作,但另一个没有,但我不知道;他们都是不安全的结构。他们如下:

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

那么,我必须改变,以使这个编译?


我相信这是SDL_BlitMap是造成这一问题的参考SDL_blit。我已经宣布它是一个代表;有什么我应该被宣布为?它的定义如下:C:

typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect, 
         struct SDL_Surface * dst, SDL_Rect * dstrect); 
+0

你能告诉我们你的SDL_Rect声明吗? –

+0

@SimonWhitehead:已添加到问题。 – mpen

+0

'SDL_Surface'怎么样?这是打破链条的东西..因为到目前为止,这为我编译。 –

回答

5

任何包含托管类型的结构都无法获取其地址。 代表是一个引用类型,因此它们也是一个托管类型。 这意味着SDL_Blitmap是一个托管类型,因为它包含对SDL_blit的托管引用,因此如果不先修复它,您将无法获取指向它的指针。

如果你试图调用该函数是在DLL已经上市,我建议你看看DllImportAttribute。(http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.100).aspx

通过结合一个DllImportAttribute公共静态外部声明,你可以调用任何你在互操作的dll中声明的全局函数。

或者您需要创建一个C/C++函数指针并调用它,这可能会变得混乱。

+0

虽然我没有试图调用它,该结构包含一个函数指针,我试图找出如何声明。我认为把它作为代表宣布是一条可行的路,但这似乎并不令人高兴。 – mpen

+1

在这种情况下,你所能做的就是将其声明为int或IntPtr - 任何大小相同的行为作为填充。 – Pharap

2

如果您不依赖不安全的代码会怎么样?尽管代码对性能/速度至关重要,但它可能会影响性能。沿此线的东西:

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

当你需要阅读的任何结构指针:

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

否则,如果你想坚持到您当前密码,尝试声明函数指针作为IntPtr而不是委托,并在运行时使用Marshal.GetDelegateForFunctionPointer创建委托。

+0

速度至关重要;这些用于绘制例程。我想我会采用你的'IntPtr'建议;这似乎工作正常,我看不出我实际上要重写blit函数,尽管这应该是一个通用库。每次调用其中一个函数时,编组一次比编组要好。 – mpen

相关问题