Discussion:
Returning an Array of C# Structures
(too old to reply)
hpw
2007-06-14 13:41:56 UTC
Permalink
Raw Message
Hi all,

i'm trying to use COM Interop to return an array of c# structures to
Native code.
I tried to marshall the Array as SAFEARRAY.

The structure:

[StructLayout(LayoutKind.Sequential)]
[ComVisible(true)]
public struct teststruct{
[MarshalAs(UnmanagedType.LPStr)]
public string string1;

[MarshalAs(UnmanagedType.LPStr)]
public string string2;

[MarshalAs(UnmanagedType.LPStr)]
public string string3;

[MarshalAs(UnmanagedType.SafeArray)]
public string[] parameters;

};

is given back via a function

[return: MarshalAs(UnmanagedType.SafeArray)]
public teststruct[]
GetTestStruct([MarshalAs(UnmanagedType.LPStr)]string strParam, int
iParam) ;

I've generated the TLB via tlbexp.exe and used the Objects in a C++
Program.

Other calls with string-arrays and int-arrays work find. But for this
particular case i get the following _com_error:
0x80028019 - Old format or invalid type library

I also tried to specifiy the SafeArraySubType.
No Effect.

Any Help would be appreciated

HPW
herc
2007-06-14 15:53:29 UTC
Permalink
Raw Message
On Jun 14, 9:41 am, hpw <***@hp-weidinger.at> wrote:

> i'm trying to use COM Interop to return an array of c# structures to
> Native code. I tried to marshall the Array as SAFEARRAY.

Question: Does it HAVE to be an array or can you return a
collection?

Personally, I HATE passing arrays (SAFEARRAYS) around in COM, they are
a real pain. If a collection is an option, look into the IEnumVARIANT
interface. I would susspect that a C# ICollection interface is a
IEnumVARIANT. Google it and I think you will find much easier ways of
dealing with this issue;)

Cartoper
hpw
2007-06-14 16:14:23 UTC
Permalink
Raw Message
> > i'm trying to use COM Interop to return an array of c# structures to
> > Native code. I tried to marshall the Array as SAFEARRAY.
>
> Question: Does it HAVE to be an array or can you return a
> collection?
>
> Personally, I HATE passing arrays (SAFEARRAYS) around in COM, they are
> a real pain. If a collection is an option, look into the IEnumVARIANT
> interface. I would susspect that a C# ICollection interface is a
> IEnumVARIANT. Google it and I think you will find much easier ways of
> dealing with this issue;)

Hi Cartoper,

thanks for your comments.

At the moment i did a similar workaround even though i do not like it:
i implemented an object with a dual-interface that allows me to read
the entires of the array.
I can pass back a reference to this Helper-Object that i can use to
read the structs.

If i pass back those things as Array (wich implements the ICollection
and IList interface) i get
an mscorlib::_Array that i can use. Unfortunately reading the items
using the IList interface always gives
me an Error "invalid argument type" if i try to read the arrays as
VARIANTs.

I havent tried using an IEnumVARIANT yet but i will also try this.

br
HPW
SteveR
2007-07-09 06:52:05 UTC
Permalink
Raw Message
This is exactly the same problem I'm having. Have you got any code samples
you could post or url's I can refer to?
--
Steve


"herc" wrote:

> On Jun 14, 9:41 am, hpw <***@hp-weidinger.at> wrote:
>
> > i'm trying to use COM Interop to return an array of c# structures to
> > Native code. I tried to marshall the Array as SAFEARRAY.
>
> Question: Does it HAVE to be an array or can you return a
> collection?
>
> Personally, I HATE passing arrays (SAFEARRAYS) around in COM, they are
> a real pain. If a collection is an option, look into the IEnumVARIANT
> interface. I would susspect that a C# ICollection interface is a
> IEnumVARIANT. Google it and I think you will find much easier ways of
> dealing with this issue;)
>
> Cartoper
>
>
hpw
2007-07-25 11:50:18 UTC
Permalink
Raw Message
Hi Steve,

sorry for the late answer.

I couldn't solve the problem - so i found a workaround for this.
I've used a wrapper for the list and returned this instead of the
array.

Alternatively you can also use one of the list-Classes provided by
System.Collections. ...

here is what i did:

[Guid("xxxxxxxxxxxxxxx")]
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ITeststructCollection {
void add(teststruct c);
int count();
teststruct get([MarshalAs(UnmanagedType.I4)] int i);
void Dispose();
};

and the implementation for this (TeststructCollection).
the call which returns the Interface looks like

TeststructCollection
GetCallEntries([MarshalAs(UnmanagedType.LPStr)]string smthing, int i);

Native code looks like this

...
_CallEntryCollectionPtr entries=engine-
>GetCallEntries(pszSmthing,i);

CoTaskMemFree(pszSmthing);

ICallEntryCollection *coll;
hResult=entries->QueryInterface(&coll);

if (FAILED(hResult)) {
char ch[255];
::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,hResult,NULL,ch,
255,NULL);
char pszErr[1024];
sprintf(pszErr,"Reading COM-Entries Error: 0x%08x - %s
\n",hResult,ch);
fprintf(stderr,pszErr);
return ;
}

int count=coll->count();
...


hope this helps.

br
HPW

On Jul 9, 8:52 am, SteveR <***@discussions.microsoft.com> wrote:
> This is exactly the same problem I'm having. Have you got any code samples
> you could post or url's I can refer to?
> --
> Steve
>
> "herc" wrote:
> > On Jun 14, 9:41 am, hpw <***@hp-weidinger.at> wrote:
>
> > > i'm trying to use COM Interop to return an array of c# structures to
> > > Native code. I tried to marshall the Array as SAFEARRAY.
>
> > Question: Does it HAVE to be an array or can you return a
> > collection?
>
> > Personally, I HATE passing arrays (SAFEARRAYS) around in COM, they are
> > a real pain. If a collection is an option, look into the IEnumVARIANT
> > interface. I would susspect that a C# ICollection interface is a
> > IEnumVARIANT. Google it and I think you will find much easier ways of
> > dealing with this issue;)
>
> > Cartoper
John xyz
2011-11-27 15:46:28 UTC
Permalink
Raw Message
http://www.4microsoftsolutions.com/post/Understanding-Structures.aspx

> On Thursday, June 14, 2007 9:41 AM hpw wrote:

> Hi all,
>
> i'm trying to use COM Interop to return an array of c# structures to
> Native code.
> I tried to marshall the Array as SAFEARRAY.
>
> The structure:
>
> [StructLayout(LayoutKind.Sequential)]
> [ComVisible(true)]
> public struct teststruct{
> [MarshalAs(UnmanagedType.LPStr)]
> public string string1;
>
> [MarshalAs(UnmanagedType.LPStr)]
> public string string2;
>
> [MarshalAs(UnmanagedType.LPStr)]
> public string string3;
>
> [MarshalAs(UnmanagedType.SafeArray)]
> public string[] parameters;
>
> };
>
> is given back via a function
>
> [return: MarshalAs(UnmanagedType.SafeArray)]
> public teststruct[]
> GetTestStruct([MarshalAs(UnmanagedType.LPStr)]string strParam, int
> iParam) ;
>
> I've generated the TLB via tlbexp.exe and used the Objects in a C++
> Program.
>
> Other calls with string-arrays and int-arrays work find. But for this
> particular case i get the following _com_error:
> 0x80028019 - Old format or invalid type library
>
> I also tried to specifiy the SafeArraySubType.
> No Effect.
>
> Any Help would be appreciated
>
> HPW


>> On Thursday, June 14, 2007 11:53 AM herc wrote:

>> On Jun 14, 9:41 am, hpw <***@hp-weidinger.at> wrote:
>>
>>
>> Question: Does it HAVE to be an array or can you return a
>> collection?
>>
>> Personally, I HATE passing arrays (SAFEARRAYS) around in COM, they are
>> a real pain. If a collection is an option, look into the IEnumVARIANT
>> interface. I would susspect that a C# ICollection interface is a
>> IEnumVARIANT. Google it and I think you will find much easier ways of
>> dealing with this issue;)
>>
>> Cartoper


>>> On Thursday, June 14, 2007 12:14 PM hpw wrote:

>>> Hi Cartoper,
>>>
>>> thanks for your comments.
>>>
>>> At the moment i did a similar workaround even though i do not like it:
>>> i implemented an object with a dual-interface that allows me to read
>>> the entires of the array.
>>> I can pass back a reference to this Helper-Object that i can use to
>>> read the structs.
>>>
>>> If i pass back those things as Array (wich implements the ICollection
>>> and IList interface) i get
>>> an mscorlib::_Array that i can use. Unfortunately reading the items
>>> using the IList interface always gives
>>> me an Error "invalid argument type" if i try to read the arrays as
>>> VARIANTs.
>>>
>>> I havent tried using an IEnumVARIANT yet but i will also try this.
>>>
>>> br
>>> HPW


>>>> On Monday, July 09, 2007 2:52 AM Steve wrote:

>>>> This is exactly the same problem I am having. Have you got any code samples
>>>> you could post or url's I can refer to?
>>>> --
>>>> Steve
>>>>
>>>>
>>>> "herc" wrote:


>>>>> On Wednesday, July 25, 2007 7:50 AM hpw wrote:

>>>>> Hi Steve,
>>>>>
>>>>> sorry for the late answer.
>>>>>
>>>>> I couldn't solve the problem - so i found a workaround for this.
>>>>> I've used a wrapper for the list and returned this instead of the
>>>>> array.
>>>>>
>>>>> Alternatively you can also use one of the list-Classes provided by
>>>>> System.Collections. ...
>>>>>
>>>>> here is what i did:
>>>>>
>>>>> [Guid("xxxxxxxxxxxxxxx")]
>>>>> [ComVisible(true)]
>>>>> [InterfaceType(ComInterfaceType.InterfaceIsDual)]
>>>>> public interface ITeststructCollection {
>>>>> void add(teststruct c);
>>>>> int count();
>>>>> teststruct get([MarshalAs(UnmanagedType.I4)] int i);
>>>>> void Dispose();
>>>>> };
>>>>>
>>>>> and the implementation for this (TeststructCollection).
>>>>> the call which returns the Interface looks like
>>>>>
>>>>> TeststructCollection
>>>>> GetCallEntries([MarshalAs(UnmanagedType.LPStr)]string smthing, int i);
>>>>>
>>>>> Native code looks like this
>>>>>
>>>>> ...
>>>>> _CallEntryCollectionPtr entries=engine-
>>>>>
>>>>> CoTaskMemFree(pszSmthing);
>>>>>
>>>>> ICallEntryCollection *coll;
>>>>> hResult=entries->QueryInterface(&coll);
>>>>>
>>>>> if (FAILED(hResult)) {
>>>>> char ch[255];
>>>>> ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,hResult,NULL,ch,
>>>>> 255,NULL);
>>>>> char pszErr[1024];
>>>>> sprintf(pszErr,"Reading COM-Entries Error: 0x%08x - %s
>>>>> \n",hResult,ch);
>>>>> fprintf(stderr,pszErr);
>>>>> return ;
>>>>> }
>>>>>
>>>>> int count=coll->count();
>>>>> ...
>>>>>
>>>>>
>>>>> hope this helps.
>>>>>
>>>>> br
>>>>> HPW
>>>>>
>>>>> On Jul 9, 8:52 am, SteveR <***@discussions.microsoft.com> wrote:
Loading...