[Mono-devel-list] Re: [Mono-list] Re: IStream implementation on Win32 for System.Drawing.Image.InitFromStream

Kornél Pál kornelpal at hotmail.com
Mon May 9 14:30:22 EDT 2005


Hi,

> Could you post the code to the mailing list, so we can comment on it?

I attached the latest version.
Note that as this is Win32 specific (GDI+ and IStream, the code itself not)
you have to run it under Windows.

Comments are welcome.

I sent a previous version to Sanjay Gupta and he sent and reply to the list
then I answered it but none of these messages arrived yet, they are waitng
for moderation...

I forwarded the whole thread at the end of this message.

ComIStreamWrapper.cs is a Stream to IStream wrapper. This is compatible with
.NET Framework COM interop without custom marshaling.
ComIStreamMarshaler.cs is a custom marshaler for UCOMIStream. It implements
CCW and RCW as well. When COM interface marshaling will be available in Mono
this is no longer required and if Mono will provide proper marshaling
support ComIStreamWrapper will be able to be used without
ComIStreamMarshaler.

These classes are based on only documented functionality.

Form1.cs is a demonstration form, it is full of hack as image creation form
a GDI+ handle is not supported using public methods.

RCW implementation is not supported on Mono as it does not implement
function pointer to delegate marshaling.
There are other limitations in Mono marshaling that could to be worked
around.

I filed the following bug reports:
http://bugzilla.ximian.com/show_bug.cgi?id=74882
http://bugzilla.ximian.com/show_bug.cgi?id=74875

Sincerely,
Kornél

----- Original Message -----
From: "Sanjay Gupta" <GSanjay at novell.com>
To: <kornelpal at kornelpal.hu>; <mono-devel-list at lists.ximian.com>
Sent: Monday, May 09, 2005 11:59 AM
Subject: Re: IStream implementation for
GdipLoadImageFromStreamandGdipSaveImageToStream on Win32


Hi Kornél,
Sorry for my misunderstanding. Your implementation is for achieving
functionality on win32 platforms, which is still missing.
If you run your program on Linux platform, both the functions
work.

I am not including nor in a position to include your source code as i have
moved
from mono project.

Friends on the list will be able to help you out.

During my development i used to rely on System.WriteLine stmt as well as
on printing stack trace, embedded within the exception thrown.

Thanx n Regards,
Sanjay

>>> Kornél Pál <kornelpal at kornelpal.hu> 5/9/2005 3:11:55 PM >>>
Hi Sanjay,

I developed the version sent to you using the source code and runtime of
Mono 1.1.6 but today I have downloaded the latest available source code
package (mono-1.1.7.20050506.tar.gz), and it has the same limitations.

Please lhave a look at "nternal void InitFromStream (Stream stream) " and
"public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters
encoderParams)" in "System.Drawing.Image.cs".

These methods implement stream handling and both of them throws a
NotImplementedException on Win32 because GdipLoadImageFromStream and
GdipSaveImageToStream require an IStream interface and Mono has no native
COM Callable Wrapper (CCW) support. I have implemented a CCW using managed
code. Note that on Linux these methods use delegates passed as parameters to
the functions that are converted to function pointers by the runtime.

Please do not include the version I sent you in Mono yet as I have some
fixes and I am working on a more proper version that uses an object that
implements ICustomMarshaler and an object that implements UCOMIStream. This
would be better as when Mono will have COM interface marshaling support the
ICustomMarshaler could be forgotten and the UCOMIStream could be used with
[MarshalAs(UnmanagedType.Interface)].

My only problem is that Mono marshaling is too much different from .NET
Framework marshaling. I have filed a bug report:
http://bugzilla.ximian.com/show_bug.cgi?id=74875
But I think I will have to work around these limitations by using IntPtrs
and the Marshal class instead of MarshalAsAttributes.

By the way I have subscribed to mono-list and mono-devel-list.

I am interested in contributing functionality that is not currently
implemented as I currently working on ASP.NET applications and I want to use
them on Windows/IIS/Microsoft ASP.NET as well as on Linux/Apache/Mono
ASP.NET.

I am new to Mono but I am experienced in C#, ASP.NET, MSIL, marshaling, ...
related to Microsoft .NET Framework but I don't know the exact
characteristics of the Mono runtime. Usually I use Windows XP and I do
primary compatibility tests of my applications with Mono on Windows and I
test them on Linux after they passed the tests on Windows.

My only problem is that on Windows/.NET Framework I can use Visual Strudio
.NET to debug my applications using breakpoints and examine the call stack
and I can use the StackTrace to obtain the source code lines when I compile
debug code to make the compiler generate a PDB file and I can obtain IL
offsets using release code with [assembly: Debuggable(true, true)] but I can
obtain only native offsets using Mono. I have tried mcs as well but I was
unable to do reasonable debugging.

Could anyone tell me how to get the exact (+/- 1 line or opcode doesn't
matter) location of an exception in Mono or Windows?

Sincerely,
Kornél

----- Original Message -----
From: "Sanjay Gupta" <GSanjay at novell.com>
To: <kornelpal at kornelpal.hu>; <mono-devel-list at lists.ximian.com>
Sent: Monday, May 09, 2005 6:26 AM
Subject: Re: IStream implementation for GdipLoadImageFromStream
andGdipSaveImageToStream on Win32


Hi Kornél,
Thanx for your efforts in making mono more stable.
GdipLoadImageFromStream and GdipSaveImageToStream were supported in mono.
BTW, Kornél, i am posting your patch to mono-devel-list, so that other
people can also
have a look at it and can comment on it.

Thanx n Regards,
Sanjay


>>> Kornél Pál <kornelpal at kornelpal.hu> 5/6/2005 10:39:19 PM >>>
Dear Sanjay and Ravindra,

I am writing this e-mail to you because I think you are the maintainer of
System.Drawing.

I have tried Mono on Windows XP with XSP and ASP.NET.

Mono is really compatible with Microsoft .NET Framework, there were only
some differences that could be worked around using some modifications in my
code.

My ASP.NET web application is generating some images using System.Drawing
(GDI+), and it needs to load images form managed resources (accessible using
a Stream object) and the write it to the HTTP output (accessible using a
Stream object).

But this is not supported in Mono, because GDI+ on Win32 requires an IStream
COM object and Mono does not have COM support yet.

Then I realized that Mono has proper P/Invoke and
System.Runtime.InteropServices.Marshal class implementation so it is
possible to implement a COM object using Delegates as COM objects are simply
object pointers and the object has a pointer to a virtual method table.

This can be implemented in managed code using documented and available
functionality.

I have created a class named GdiPlusStream that implements the IStream
interface.
The class provides identical behaviour on Mono and .NET Framework as well.

I attached a zip file containing this class and a demonstration project.

Some comments on the class:

It is implemented without any hack only uses documented functionality.

The only exception is the function GetHRForException. It is required as
Marshal.GetHRForException is not implemented in Mono altough all the
Exception classes implement the HResult propery with the proper value.

But this isn't a real hack as the propery HResult is documented but it is
protected and requires use of reflection.

This function should be moved to Marshal.GetHRForException.

The class provides a proper COM IStream implementation with reference
counting and Exception to HRESULT transformation.

It has a static vtable just like real COM objects as the delegate wrappers
are requiring a lot of memory and GDI+ uses the stream until the Image
object is released. Note that all the unmanaged memory allocated by the
class is freed using destructors. The static vtable is allocated when the
class is used for the first time and is freed when the AppDomain is
unloaded. Note that the delegates have to kept alive as the runtime is
wrapping the delegates and not the functions.

The COM object contains a weak reference GCHandle of the managed object to
be able to use instance members.

The object is kept alive until it is released by all the COM referrers even
if it has no managed references but will be released to GC if it has no more
COM references. It uses a HandleRef to maintain a managed reference while
the object is in use by managed code.

I think the stream functionality implemented in the class is enough for
GDI+. It copies the base Stream to a MemoryStream like the .NET Framework
implementation if it does not support seeking as GDI+ does a lot of seeking
operations and is reading the image from the stream every time it is
rendered.

The demonstration Form is full of hack but it is just an example of using
GdiPlusStream and System.Drawing has no public constructors, methods,
properties to create an Image object form a GDI+ image handle or to obtain
the handle.

Please include this IStream implementation in Mono to make Mono able to load
images and save images to files.

Sincerely,
Kornél
-------------- next part --------------
A non-text attachment was scrubbed...
Name: GdipStream.zip
Type: application/x-zip-compressed
Size: 21693 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20050509/3cbf1328/attachment.bin 


More information about the Mono-devel-list mailing list