470,573 Members | 1,582 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,573 developers. It's quick & easy.

Passing a struct between managed and unmanged code

2
I have create a .Net component which exposes an interface with two methods. The first method takes an array of structs as a parameter the other method returns an array of (the same tyoes of) structs.

When I get the array structures from my second method in unmanaged c++, I cannot regonize any of the parameters in the structures. But if I pass the same pointer to the first method in my interface and look at the values in .net then thay are all intact.

Can anyone tell my how to read these values in unmanaged c++?

Code and more explanations:
The regasm of the .net code gives an interface in the .tlh file like this:
HRESULT Input( SAFEARRAY * calibRecords );
SAFEARRAY * Output( );
and my stryct:
MyRecord { double r; };

In c++ i get the dispatch interface to the library and then do a queryInterface for my interface like this:

ITool *p;
HRESULT hr = pDisp->QueryInterface(&p);
SAFEARRAY *psa = p->Output();

I know there are 2 elements in the array, so I do the following:
MyRecord *cc=new MyRecord[2];

hr = SafeArrayAccessData(psa, reinterpret_cast<void**>(&cc));

But ther values in cc is NOT the correct ones.
If I then do a hr = p->Input(psa); and looks at the values in the .net application then all looks fine.

Please help me...
Oct 22 '07 #1
3 4195
weaknessforcats
9,208 Expert Mod 8TB
*p;
HRESULT hr = pDisp->QueryInterface(&p);
SAFEARRAY *psa = p->Output();

I know there are 2 elements in the array, so I do the following:
MyRecord *cc=new MyRecord[2];

hr = SafeArrayAccessData(psa, reinterpret_cast<void**>(&cc));
First, SafeArrayAccessData() requires a SAFEARRAY* obtained from SafeArrayCreate(). I do not know what p->Output() is doing.

Second, SafeArrayAccessData() needs the address of a pointer since it will allocate the SAFEARRAY and need to return its address to you. So this code:
MyRecord *cc=new MyRecord[2];
probably need to be:
Expand|Select|Wrap|Line Numbers
  1. SAFEARRAY* arr;
  2.  
and the call need to look like:
Expand|Select|Wrap|Line Numbers
  1. hr = SafeArrayAccessData(psa, &arr);
  2.  
Third, you can't have a SAFEARRAY of MyRecord structs. The elements of a SAFEARRAY are limited to specific types. In your case you need a SAFEARRAY of VARIANT where the variant contains the double. You might be able to pass a MyRecord by reference in a VARIANT and use IRecordInfo to parse it.
Oct 22 '07 #2
cskarp
2
Hi,

Thanks for your answer.

I know that when you creates a SAFEARRAY you have to call SafeArrayCreate() before you can use it. But in this context .net returns a SAFEARRAY in p->Output(), which I suppose is initialized and filled with the data from my .net component. I the .net component I create and fill an array of classes - which contains only data. So in .net the interface is "MyRecord[] Output();"

The AccessData you are describing is also what I have done and afterwards the data is not what I expect.

I really didn't knew that I could not pass a SAFEARRAY of MyRecord between the components. I know that I could create a SAFEARRAY of doubles but I have simplyfied the MyRecord here, normally it contains a lot of other data and therefor I cannot use an array of doubles.
Oct 23 '07 #3
weaknessforcats
9,208 Expert Mod 8TB
You can have your MyRecord in a VARIANT as IRecordInfo. Then you create your SAFEARRAY as an array of VARIANT.

Check [url=http://msdn2.microsoft.com/en-us/library/ms221627.aspx]this[\url].
And [url=http://msdn2.microsoft.com/en-us/library/ms221482.aspx]this[\url] where is mentions using FADF_VARIANT
Oct 23 '07 #4

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

1 post views Thread by codymanix | last post: by
2 posts views Thread by Sandy | last post: by
1 post views Thread by livre | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.