> 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 < [email protected]> wrote: > On Wed, Dec 30, 2009 at 9:21 AM, Andy Selvig <[email protected]> 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 >
_______________________________________________ Gtk-sharp-list maillist - [email protected] http://lists.ximian.com/mailman/listinfo/gtk-sharp-list
