Groups | Blog | Home
all groups > dotnet interop > october 2004 >

dotnet interop : marsal string array inside a struct


Luis Abreu
10/5/2004 11:20:49 PM
I want to implement the interface IPerPropertyBrowsing. I'm having some
doubts regarding the correct implementation of this method:

HRESULT GetPredefinedStrings(
DISPID dispID, //Dispatch identifier for property
CALPOLESTR *pcaStringsOut, //Receives a pointer to an array of
//strings
CADWORD *pcaCookiesOut //Receives a pointer to array of DWORDs
);


I've defined this method like this in my C# code:

public uint GetPredefinedStrings(int dispid, out CALPOLESTR strOut, out
CADWORD cookiesOut)
{
....
}

my problem is the definition of struct CALPOLESTR. It looks like this:

[
StructLayout(LayoutKind.Sequential),
ComVisible( false )
]
public struct CALPOLESTR
{
public uint count;
[ComConversionLoss()]public IntPtr elems; //this is supposed to take an
array of strings
}

elems should contain an array of strings allocated through CoTaskMemAlloc.
so I though that I should do someting like this:

string [] _beepString = new string [] { "Yes", "No" };
IntPtr [] arr = new IntPtr[2];
for( int i = 0; i < _beepStrings.Length; i++ )
{
arr[i] = Marshal.StringToHGlobalAnsi( _beepStrings[i] );
}
//DOUBT: how to pass array of IntPtr to IntrPtr
strOut.count = Convert.ToUInt32( _beepStrings.Length );
break;

I have several doubts :
1.) is this the correct approach? maybe there's a simple way to pass an
array of strings which I'm not recalling...
2.) how can I pass the IntPtr array to the IntPtr member? btw, show I use
GC.KeepAlive?

thanks

--
---
Regards,
Luis Abreu
http://weblogs.pontonetpt.com/luisabreu
http://www.pontonetpt.com

Luis Abreu
10/5/2004 11:26:03 PM
[quoted text, click to view]

sorry, this should be:

arr[i] = Marshal.StringToCoTaskMemUni( _beepStrings[i] );


--
---
Regards,
Luis Abreu
http://weblogs.pontonetpt.com/luisabreu
http://www.pontonetpt.com

Mattias Sjögren
10/6/2004 7:56:04 PM

[quoted text, click to view]

You can do it like this

strOut.elems = Marshal.AllocCoTaskMem(_beepStrings.Length *
IntPtr.Size);
for( int i = 0; i < _beepStrings.Length; i++ )
{
Marshal.WriteIntPtr(strOut.elems, i * IntPtr.Size,
Marshal.StringToCoTaskMemUni( _beepStrings[i] );
}


[quoted text, click to view]

There's no managed method do do that in one call. You can write one
value at the time with Marshal.WriteIntPtr like above.


[quoted text, click to view]

On which object?



Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Luis Abreu
10/6/2004 9:03:34 PM
Hello Mattias.

tahnks for the help.

--
---
Regards,
Luis Abreu
http://weblogs.pontonetpt.com/luisabreu
http://www.pontonetpt.com

[quoted text, click to view]

Luis Abreu
10/6/2004 9:30:25 PM
oh, and btw, I was refering to the out params...shouldn't I use GC.KeepAlive
on them?

--
---
Regards,
Luis Abreu
http://weblogs.pontonetpt.com/luisabreu
http://www.pontonetpt.com

[quoted text, click to view]

Mattias Sjögren
10/16/2004 9:30:30 PM

[quoted text, click to view]

Nope. Since (I assume) they are stack allocated their lifetime isn't
affected by the GC.



Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Luis Abreu
10/17/2004 2:30:06 AM
Hello again Mattias.

[quoted text, click to view]
hum...I also thought that.I've tried the code you've showed me in a previous post, but unfortunatelly it doesn't work..it seems correct, but the vb6 window doesn't show the strings...I'd really love to know what must I do to implement the interface IPerPropertyBrowsing in C#...


--
Regards,
Luis Abreu
http://weblogs.pontonetpt.com/luisabreu
http://www.pontonetpt.com
AddThis Social Bookmark Button