Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot declare pointer to non-unmanaged type

Tags:

c#

I'm trying to learn how to write a wrapper around a DLL and I've hit a bit of a road-block. I've got a struct 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 it, I do have a pointer to another struct. I'm trying to figure out what the difference between these two structs is that makes one work but the other doesn't, but I'm not sure; they're both unsafe structs. They are as follows:

[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 have to change to make this compile?


I believe it's the reference to SDL_blit in SDL_BlitMap that's causing the problem. I've declared it as a delegate; is there something else I should be declaring it as? It's defined as this, in C:

typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect,
                         struct SDL_Surface * dst, SDL_Rect * dstrect);
like image 756
mpen Avatar asked Mar 24 '23 06:03

mpen


1 Answers

Any struct that contains a managed type cannot have its address taken. Delegates are a reference type, therefore they are also a managed type. This means that an SDL_Blitmap is a managed type because it contains a managed reference to an SDL_blit, thus you cannot get a pointer to it without fixing it first.

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

By combining a public static extern declaration with a DllImportAttribute, you can invoke any global function declared in the dll you are interop-ing.

Alternatively you'll need to create a C/C++ side function that takes a function pointer and invokes it, which could get messy.

like image 199
Pharap Avatar answered Apr 06 '23 19:04

Pharap