[Gtk-sharp-list] Access Violations with Mono.Cairo on Windows

Andy Selvig ajselvig at gmail.com
Wed Dec 30 16:36:44 EST 2009


> You should probably use a GCHandle to pin the byte[]:
> var gch = new GCHandle (imageData, GCHandleType.Pinned);
> and make sure you gch.Free() when you dispose the surface.

Thanks, Michael. That was it. Just a small syntax note for others that might
be reading this, the gc handle is created with:

gch = GCHandle.Alloc(imageData, GCHandleType.Pinned);

But, yeah, that fixed it. Works great now.

> Alternatively, you could modify Mono.Cairo to:
> * use Marshal.AllocHGlobal to malloc some unmanaged memory, and get an
> IntPtr to it
> * use Marshal.Copy to mcpy the byte[] to the new memory
> * change the p/invoke signature to use a IntPtr instead of a byte[]
> * use Marshal.FreeHGlobal to free the memory when the surface is disposed

I guess I don't have any fundamental problems with modifying Mono.Cairo, but
it seems like it's more likely that there's something wrong with me setup. I
can't be the only one who is using ImageSurfaces on Windows. There must be
an ImageSurface in MonoDevelop somewhere, right?

Plus, I'm still troubled by the fact that the API is different for my
Windows version of Mono.Cairo while the versions seem to be the same. I'll
have to look further into that.

But, yes, if this is really what you have to do for image surfaces in
Mono.Cairo on Windows, then it's a bug and should be fixed IN Mono.Cairo. It
is unreasonable to expect users of a managed library (even if it's just a
wrapper to an unmanaged one) to have to manage their own memory.

If no one else out there can confirm that I'm doing something wrong (using
an old version of the library, have some sort of version mismatch between
the managed and unmanaged dll's, etc) then I'll file a bug.

Thanks again.

On Wed, Dec 30, 2009 at 2:46 PM, Michael Hutchinson <
m.j.hutchinson at gmail.com> wrote:

> On Wed, Dec 30, 2009 at 9:21 AM, Andy Selvig <ajselvig at gmail.com> wrote:
> > It is marked as obsolete (at least it is in whatever version I'm using on
> > Linux), but from the code you linked to it simply calls the valid
> > constructor anyway, so it should do the exact same thing.
> >
> > Plus, it does work initially. It takes a couple seconds to fail, but
> before
> > that, it renders exactly the way it should.
>
> Ah, I missed the base call.
>
> OK, so the likely problem here is that the underlying native code of
> the imagesurface expects to keep a reference to the  byte[] that's
> passed to it. The delay implies that it's marshalled as a pointer
> directly into the managed byte[], and .NET's compacting GC is moving
> the byte[] afterwards. Things that you pass into p/invokes are pinned
> for the duration of the call, but not afterwards.
>
> You should probably use a GCHandle to pin the byte[]:
> var gch = new GCHandle (imageData, GCHandleType.Pinned);
> and make sure you gch.Free() when you dispose the surface.
>
> Alternatively, you could modify Mono.Cairo to:
> * use Marshal.AllocHGlobal to malloc some unmanaged memory, and get an
> IntPtr to it
> * use Marshal.Copy to mcpy the byte[] to the new memory
> * change the p/invoke signature to use a IntPtr instead of a byte[]
> * use Marshal.FreeHGlobal to free the memory when the surface is disposed
>
> --
> Michael Hutchinson
> http://mjhutchinson.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/gtk-sharp-list/attachments/20091230/d1e70a4d/attachment.html 


More information about the Gtk-sharp-list mailing list