Red Gate forums :: View topic - Marshaling Struct w/ VARIANT from C++ to C#
Return to www.red-gate.com RSS Feed Available

Search  | Usergroups |  Profile |  Messages |  Log in  Register 
Go to product documentation
PInvoke.Net
PInvoke.Net forum

Marshaling Struct w/ VARIANT from C++ to C#

Search in PInvoke.Net forum
Post new topic   Reply to topic
Jump to:  
Author Message
jaskiewiczm



Joined: 24 Apr 2008
Posts: 5

PostPosted: Thu Apr 24, 2008 8:53 pm    Post subject: Marshaling Struct w/ VARIANT from C++ to C# Reply with quote

Hi,
I'm trying to marshal over a struct that contains 2 VARIANTs from C++ to C# and of course having some trouble.
I pass a pointer for my struct into a C# function and on the C# side handle it as a IntPtr. At that point, I use PtrToStructure to turn it into a C# struct that has 2 items of type "object" in it. The app crashes at this point.
My question is, are there special considerations necessary for marshaling over a struct that contains VARIANTs? I can do the marshaling over w/ 2 ints just fine. The moment the VARIANT comes into play everything starts crashing.
All suggestions are greatly appreciated.
mj
Back to top
View user's profile Send private message
Robert



Joined: 30 Oct 2006
Posts: 428
Location: Cambridge, UK

PostPosted: Thu Apr 24, 2008 10:52 pm    Post subject: Reply with quote

Hi,

I've not tried with VARIANTS myself, but I have had to do something similar with PROPVARIANTS, and the structure looks similar from MSDN.

Try creating a VARIANT structure in C# which mirrors the C++ struct shown on MSDN, specifically with the vt parameter in there as well. You'll probably need to use explicit layouts, at which point you can get something that sort of pretends to be the C# equivalent of a union (by having the field offset of multiple fields being set to the same value).

Hope that helps,
Robert
_________________
Robert Chipperfield
Developer, Red Gate Software Ltd
Back to top
View user's profile Send private message MSN Messenger
jaskiewiczm



Joined: 24 Apr 2008
Posts: 5

PostPosted: Fri Apr 25, 2008 4:04 pm    Post subject: C# VARIANT Port Reply with quote

Hi Robert,
I'm taking your advice regarding implementing the C# explicit struct that's a VARIANT. The VARIANT type has a struct in a struct in a struct (for a total of 3) so that's what I'm implementing as well.
My implementation has tagVariant containing __tagVariant containing __tagBRecord.
My question is, what is the length of a complete struct? Is it just the length of its parts? __tagBRecord has 2 IntPtrs in it so is __tagBRecord's length 8 bytes? I'm trying to get these offsets right.
Again, thanks for your help,
mj

[StructLayout(LayoutKind.Explicit)]
public struct tagVARIANT
{
__tagVARIANT tagVariant;
IntPtr decVal;
}

[StructLayout(LayoutKind.Explicit)]
public struct __tagVARIANT
{
[FieldOffset(0)] short vt; // VARTYPE vt;
[FieldOffset(2)] short wReserved1; // WORD wReserved1;
[FieldOffset(4)] short wReserved2; // WORD wReserved2;
[FieldOffset(6)] short wReserved3; // WORD wReserved3;
//union
//{
[FieldOffset(Cool] long llVal; // LONGLONG llVal;
[FieldOffset(Cool] int lVal; // LONG lVal;
[FieldOffset(Cool] byte bVal; // BYTE bVal;
[FieldOffset(Cool] short iVal; // SHORT iVal;
[FieldOffset(Cool] int fltVal; // FLOAT fltVal;
[FieldOffset(Cool] long dblVal; // DOUBLE dblVal;
[FieldOffset(Cool] short boolVal; // VARIANT_BOOL boolVal;
//shit! _VARIANT_BOOL bool;
[FieldOffset(Cool] int scode; // SCODE scode;
[FieldOffset(Cool] long cyVal; // CY cyVal;
[FieldOffset(Cool] long date; // DATE date;
[FieldOffset(Cool] IntPtr bstrVal; // BSTR bstrVal;
[FieldOffset(Cool] IntPtr punkVal; // IUnknown *punkVal;
[FieldOffset(Cool] IntPtr pdispVal; // IDispatch *pdispVal;
[FieldOffset(Cool] IntPtr parray; // SAFEARRAY *parray;
[FieldOffset(Cool] IntPtr pbVal; // BYTE *pbVal;
[FieldOffset(Cool] IntPtr piVal; // SHORT *piVal;
[FieldOffset(Cool] IntPtr plVal; // LONG *plVal;
[FieldOffset(Cool] IntPtr pllVal; // LONGLONG *pllVal;
[FieldOffset(Cool] IntPtr pfltVal; // FLOAT *pfltVal;
[FieldOffset(Cool] IntPtr pdblVal; // DOUBLE *pdblVal;
[FieldOffset(Cool] IntPtr pboolVal; // VARIANT_BOOL *pboolVal;
[FieldOffset(Cool] IntPtr pbool; // _VARIANT_BOOL *pbool;
[FieldOffset(Cool] IntPtr pscode; // SCODE *pscode;
[FieldOffset(Cool] IntPtr pcyVal; // CY *pcyVal;
[FieldOffset(Cool] IntPtr pdate; // DATE *pdate;
[FieldOffset(Cool] IntPtr pbstrVal; // BSTR *pbstrVal;
[FieldOffset(Cool] IntPtr ppunkVal; // IUnknown **ppunkVal;
[FieldOffset(Cool] IntPtr ppdispVal; // IDispatch **ppdispVal;
[FieldOffset(Cool] IntPtr pparray; // SAFEARRAY **pparray;
[FieldOffset(Cool] IntPtr pvarVal; // VARIANT *pvarVal;
[FieldOffset(Cool] int byref; // PVOID byref;
[FieldOffset(Cool] byte cVal; // CHAR cVal;
[FieldOffset(Cool] short uiVal; // USHORT uiVal;
[FieldOffset(Cool] int ulVal; // ULONG ulVal;
[FieldOffset(Cool] long ullVal; // ULONGLONG ullVal;
[FieldOffset(Cool] int intVal; // INT intVal;
[FieldOffset(Cool] int uintVal; // UINT uintVal;
[FieldOffset(Cool] IntPtr pdecVal; // DECIMAL* pdecVal;
[FieldOffset(Cool] IntPtr pcVal; // CHAR *pcVal;
[FieldOffset(Cool] IntPtr puiVal; // USHORT *puiVal;
[FieldOffset(Cool] IntPtr pulVal; // ULONG *pulVal;
[FieldOffset(Cool] IntPtr pullVal; // ULONGLONG *pullVal;
[FieldOffset(Cool] IntPtr pintVal; // INT *pintVal;
[FieldOffset(Cool] IntPtr puintVal; // UINT *puintVal;

[FieldOffset(Cool] __tagBRECORD tagBRecord;
//struct __tagBRECORD
// {
// PVOID pvRecord;
// IRecordInfo *pRecInfo;
// } __VARIANT_NAME_4;
} // __tagVariant

[StructLayout(LayoutKind.Explicit)]
public struct __tagBRECORD
{
[FieldOffset(0)] IntPtr pvRecord; // PVOID pvRecord;
[FieldOffset(4)] IntPtr pRecInfo; // IRecordInfo *pRecInfo;
} // __VARIANT_NAME_4;
Back to top
View user's profile Send private message
Robert



Joined: 30 Oct 2006
Posts: 428
Location: Cambridge, UK

PostPosted: Mon Apr 28, 2008 7:31 am    Post subject: Re: C# VARIANT Port Reply with quote

jaskiewiczm wrote:
Hi Robert,
My question is, what is the length of a complete struct? Is it just the length of its parts? __tagBRecord has 2 IntPtrs in it so is __tagBRecord's length 8 bytes? I'm trying to get these offsets right.
Again, thanks for your help,
mj


Hi,

If you're laying out it explicitly, the easiest way to calculate the length is to add the size of the final field to that field's offset - so in the case of your __tagBRecord, 4+4=8 as you suggested. In this case that's also equal to the sum of the components, and most of the time I think that's probably true, but if there's unused space in the struct somewhere, it might not be.

I think all that's true Smile

Rob
_________________
Robert Chipperfield
Developer, Red Gate Software Ltd
Back to top
View user's profile Send private message MSN Messenger
jaskiewiczm



Joined: 24 Apr 2008
Posts: 5

PostPosted: Mon Apr 28, 2008 2:11 pm    Post subject: Reply with quote

Robert,
When I'm attempting my Variant marshal via PtrToStructure, it hits that line and then nothing! It doesn't execute any subsequent lines and no exception is thrown.
The question that comes to mind for me is, since my structure that contains the VARIANTs inside contains the actual VARIANTs and not pointers to VARIANTs, I can't quite do a PtrToStructure call. What should I do instead?
Thanks,
mj
Back to top
View user's profile Send private message
Robert



Joined: 30 Oct 2006
Posts: 428
Location: Cambridge, UK

PostPosted: Mon Apr 28, 2008 2:23 pm    Post subject: Reply with quote

Hi,

Hmm, not quite sure what's happening there then. You shouldn't need to do a PtrToStructure call on the variant within a variant; it should just happen I think. However, I'm now reaching the edge of my knowledge about C#'s interop... I live in managed land for the most part when I can!

Sorry I can't be more helpful - all I can suggest is to keep playing around with it and see where you get.

Rob
_________________
Robert Chipperfield
Developer, Red Gate Software Ltd
Back to top
View user's profile Send private message MSN Messenger
jaskiewiczm



Joined: 24 Apr 2008
Posts: 5

PostPosted: Mon Apr 28, 2008 2:29 pm    Post subject: Reply with quote

Robert,
Made a little breakthrough. My struct that I pass from C++ to C# looks like this.
struct foobar{
VARIANT X;
VARIANT Y;
}

I turned the VARIANT references into pointers and it works fine. I can exchange integers across the interface.
What do I have to do to do this w/ references?
mj
Back to top
View user's profile Send private message
Robert



Joined: 30 Oct 2006
Posts: 428
Location: Cambridge, UK

PostPosted: Mon Apr 28, 2008 2:37 pm    Post subject: Reply with quote

I assume by that you mean when the VARIANT's target is a reference?

I'd guess at that point you get an IntPtr out of the the VARIANT, then PtrToStructure or PtrToIUnknown or whatever it to get the ComObject that you want to get out. Haven't tried doing it though Smile

Cheers,
Robert
_________________
Robert Chipperfield
Developer, Red Gate Software Ltd
Back to top
View user's profile Send private message MSN Messenger
jaskiewiczm



Joined: 24 Apr 2008
Posts: 5

PostPosted: Mon Apr 28, 2008 4:51 pm    Post subject: Reply with quote

Robert,
Yeah, it's a reference. I think what I'm going to finally settle on is expanding the C++ API to include 2 pointers to VARIANTs and then just access those pointers instead of the references.
I tried to create an IntPtr that would point to the references but I had no luck.
Thanks for all the advice.
mj
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic All times are GMT + 1 Hour
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group