Convert Interface definition to VB.NET

C

Charles Law

Can anyone convert the following C++ interface definition to VB.NET? I have
had a go, but I cannot make the Load function work and the IsDirty function
gives an error (Object not set to an instance).

MIDL_INTERFACE("7FD52380-4E07-101B-AE2D-08002B2EC713")
IPersistStreamInit : public IPersist
{
public:
virtual HRESULT STDMETHODCALLTYPE IsDirty( void) = 0;
virtual HRESULT STDMETHODCALLTYPE Load(/* [in] */ LPSTREAM pStm) =
0;
virtual HRESULT STDMETHODCALLTYPE Save(/* [in] */ LPSTREAM pStm, /*
[in] */ BOOL fClearDirty) = 0;
virtual HRESULT STDMETHODCALLTYPE GetSizeMax(/* [out] */
ULARGE_INTEGER *pCbSize) = 0;
virtual HRESULT STDMETHODCALLTYPE InitNew( void) = 0;
};

One thing I am not sure of is whether I have to include an 'Inherits
IPersist' at the start (which itself would include an Inherits IUnknown), or
not. If so, I would also need VB.NET versions of these other two interfaces.

TIA

Charles
 
V

Vadim Melnik

Hi,
Can anyone convert the following C++ interface definition to VB.NET? I have
had a go, but I cannot make the Load function work and the IsDirty function
gives an error (Object not set to an instance).

Can you show non-working VB.NET implementation of IPersistStreamInit
interface? I don't have VB .NET IPersistStreamInit implementation, only C#
one, but probably I'll be able tell you what is wrong.
One thing I am not sure of is whether I have to include an 'Inherits
IPersist' at the start (which itself would include an Inherits IUnknown), or
not.

Not you shouldn't. Note, .NET declaration for IPersistStreamInit should
contain methods for base interfaces as well (IPersist), in vtable order.


...
Regards,
Vadim.
 
M

Mattias Sjögren

Charles,
One thing I am not sure of is whether I have to include an 'Inherits
IPersist' at the start

You can, but you still have to duplicate the base interface methods in
the derived interface. See below

(which itself would include an Inherits IUnknown)

IUnknown shouldn't be declared, since you don't write your own
implementation for it. The runtime takes care of it.


Try it like this

<ComImport(), Guid("0000010c-0000-0000-C000-000000000046"), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IPersist
Sub GetClassID(ByRef pClassId As Guid)
End Interface

<ComImport(), Guid("7FD52380-4E07-101B-AE2D-08002B2EC713"), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IPersistStreamInit : Inherits IPersist
Shadows Sub GetClassID(ByRef pClassId As Guid)
<PreserveSig()> _
Function IsDirty() As Integer
Sub Load(ByVal pStm As IStream)
Sub Save(ByVal pStm As IStream, _
<MarshalAs(UnmanagedType.Bool)> ByVal fClearDirty As Boolean)
Sub GetMaxSize(ByRef pCbSize As Long)
Sub InitNew()
End Interface



Mattias
 
C

Charles Law

Hi Vadim

I have implemented Mattias's suggestion in the thread following this one
which gives better results than I was getting, but I am still not quite
there yet.

I will explain in the other thread.

Thanks for your reply.

Regards

Charles
 
C

Charles Law

Hi Mattias

I have implemented your suggestion and I now get much more sensible results.

IsDirty() now returns 1, which is more what I expect. However, although
Load() goes off for several seconds it does not load my HTML into the
browser.

It may not be the interface definition now, but could be the way I am
getting my HTML into the stream.

I have copied the example from the MSDN article "HOW TO: Wrap a UCOMIStream
in a Stream Class in Visual Basic .NET". This allows me to put an HTML
string into a UCOMIstream, which I am passing to the Load() function, but it
is not rendering even simple HTML, and when I view source, my HTML is
missing.

Although your definition uses IStream, can I replace this with UCOMIstream?
Is there another, easier way to get some string data into an
IStream/UCOMIstream object, that I can pass to the Load() function,
preferably within VB.NET, without having to resort to an unmanaged C++ DLL?

Thanks for your help.

Regards

Charles
 
V

Vadim Melnik

Hi Charles,
I have copied the example from the MSDN article "HOW TO: Wrap a UCOMIStream
in a Stream Class in Visual Basic .NET". This allows me to put an HTML
string into a UCOMIstream, which I am passing to the Load() function, but it
is not rendering even simple HTML, and when I view source, my HTML is
missing.

I'd propose unmanaged and more efficient way- use Marshal.StringToHGlobalXXX
to retrieve string unmanaged memory, and then call CreateStreamOnHGlobal API
via PInvoke. And in Mattias definition you can update IStream with
UCOMIStream.

...
Regards,
Vadim.
 
C

Charles Law

Vadim

Sorry to appear dim, but is this something I can do entirely from within
VB.NET? I see the Marshal.StringToHGlobalXXX functions, but not the
CreateStreamOnHGlobal function. You refer to this as an API, so does it need
a Declare? I don't suppose you have the appropriate VB.NET version?

After passing the resultant stream to the Load() function, do I have to
release the stream/memory?

Thanks for your help.

Regards

Charles
 
V

Vadim Melnik

Charles,

I talked about unmanaged way, CreateStreamOnHGlobal is not part of .NET
Framework, it's inside "ole32.dll" . Use DllImportAttribute to import this
API to VB.NET. Unfortunately I am not well familiar with VB, below just code
prototype, so please forgive me possible errors:

<DllImport("OLE32.DLL")> _
Public Shared Sub CreateStreamOnHGlobal(hGlobal As IntPtr, fDelete bool As
Boolean, ByRef stm As UCOMIStream)
End Sub
After passing the resultant stream to the Load() function, do I have to
release the stream/memory?

It depends on the way you declare/invoke CreateStreamOnHGlobal and Load.
HGLOBAL returned from Marshal.StringToHGlobal need to be released by
FreeHGlobal call. CreateStreamOnHGlobal has options (2nd parameter) allowing
to automatically invoke GlobalFree for passed HGLOBAL handle, when stream
will be released. So if you set this option to true, FreeHGlobal call in
unnecessary.

Regarding stream interface pointer - for current case CLR automatically will
release stream. You can force it by Marshal.ReleaseComObject call.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top