Groups | Blog | Home
all groups > dotnet interop > september 2005 >

dotnet interop : Marshaling a pointer type



Mattias Sjögren
9/14/2005 12:00:00 AM

[quoted text, click to view]

I suggest you change the parameter type to an array, as described in
the section "Conformant C-Style Arrays" at

http://msdn.microsoft.com/library/en-us/cpguide/html/cpconeditinginteropassembly.asp


Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Tahir Sultan
9/14/2005 5:49:06 AM
I am developing an application in C# using Microsoft visual studio .NET 2003.
Basically, I imported a com dll in my application by adding reference to the
COM dll. The com event in the original dll has the following signature:

HSESULT AddModifyGroupIndication(
[in] unsigned long groupListSize,
[in, size_is(groupListSize)] groupListStruct* groupList)

where groupListSize is number of items (structures) the groupList pointer is
pointing to and
groupList is a pointer to first item (structure of type groupListStruct) in
the memory.

when I imported the dll, the .NET interop marshaller converted the above
event as follows:

..method public hidebysig newslot abstract virtual
instance void AddModifyGroupIndication(
[in] valuetype unsigned int32 groupListSize,
[in] valuetype TCSAPILib.groupListStruct& groupList) runtime managed
internalcall

As shown above the pointer (groupList) to first structure in the memory got
converted to a reference (ref) to the structure.

I am doing the following in AddModifyGroupIndication event handler in C# to
get all the items (structures) but it does not work:

------------------
private void RadioSubscriberManagerClass_AddModifyGroupIndication(
uint groupListSize,
ref TCSAPILib.groupListStruct groupList)
{

IntPtr fp;
IntPtr np;
TCSAPILib.groupListStruct obj ;

unsafe
{
int size = System.Runtime.InteropServices.Marshal.SizeOf(typeof
(TCSAPILib.groupListStruct ));

fp = new IntPtr(size*(groupListSize));
try
{
fp = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(size* (int)
groupListSize);

System.Runtime.InteropServices.Marshal.StructureToPtr groupList,fp,true);

for ( int i = 0; i < groupListSize; i ++ )
{
np = new IntPtr((int)fp + (i * size));


obj = (TCSAPILib.groupListStruct )
System.Runtime.InteropServices.Marshal.PtrToStructure( np,
typeof(TCSAPILib.groupListStruct ));

OnDebugEvt("---"+obj.groupAddress.ssi.ToString()); //debug
}
}
catch (Exception e1)
{
OnDebugEvt("---Exception: "+e1.ToString());
}
finally
{
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(fp);
}

}

-------------------------------

The problem----
1. The problem is StructureToPtr method seems to be coping only first
structure from the memory.
2. As we cannot not get memory address of a managed type (groupList), how
would I get the remaining items (structures) in the memory in my event
handler.

Tahir Sultan
9/15/2005 2:00:09 AM
Mattias,

I have already tried this solution but it did not work. What happened was I
did not get the event at all. I mean the the AddModifyGroupIndication event
never got fired. It could be that the actual groupList type is a pointer as
defined on the actual interface and we are not allowed to marshal it to an
array type. Please suggest any other solution.----Thanks.



[quoted text, click to view]
Mattias Sjögren
9/16/2005 11:34:31 PM
Tahir,

[quoted text, click to view]

Well the only other option I can think of is to change the parameter
type to an IntPtr and do the copying yourself.

But using an array should work if done right.


Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Tahir Sultan
9/20/2005 6:58:04 AM
Mattias,

I have tried many times but I am not getting AddModifyGroupIndication
event. I did the following changes to Interop.TCSAPILib.il file:

1. .method public hidebysig newslot abstract virtual
instance void AddModifyGroupIndication(
[in] unsigned int32 groupListSize,
[in] valuetype TCSAPILib.groupListStruct& groupList) runtime
managed internalcall

--> Replaced with
.method public hidebysig newslot abstract virtual
instance void AddModifyGroupIndication(
[in] unsigned int32 groupListSize,
[in] valuetype TCSAPILib.groupListStruct[] marshal([])
groupList) runtime managed internalcall

2. .method public virtual instance void
Invoke(
[in] unsigned int32 groupListSize,
[in] valuetype TCSAPILib.groupListStruct& groupList) runtime
managed

---> Replaced with
.method public virtual instance void
Invoke(
[in] unsigned int32 groupListSize,
[in] valuetype TCSAPILib.groupListStruct[] marshal([])
groupList) runtime managed

3. .method public virtual instance void
AddModifyGroupIndication(
unsigned int32 A_1,
valuetype TCSAPILib.groupListStruct& groupList A_2) cil
managed

---> Replaced with
.method public virtual instance void
AddModifyGroupIndication(
unsigned int32 A_1,
valuetype TCSAPILib.groupListStruct[] marshal([])
groupList A_2) cil managed

Then, I generated a new dll from this modified Interop.TCSAPILib.il files,
removed refernce to old dll and added a reference to this newly generated
dll. When, I hooked up this AddModifyGroupIndication event with modifed
parameter, I got the event signature with the following parameters in my C#
code:

uint groupListSize,
TCSAPILib.groupListStruct[] groupList

This event is getting fired by the Com Server but I do not get it. Could
you please identify if I am missing something OR I am doing wrong
modification to the Interop.TCSAPILib.il file.----Thanks.







[quoted text, click to view]
Tahir Sultan
9/21/2005 8:41:12 AM
Mattias,

It works. Thanks. Basically, I tried with IntPtr and it worked. Now, I
think IntPtr points to unmanaged heap and Com server is responsible to free
the memory. Is that right?

Thanks.

[quoted text, click to view]
Mattias Sjögren
9/22/2005 11:18:59 PM
[quoted text, click to view]

Yes, since it's an in parameter the caller frees it.


Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Tahir Sultan
9/23/2005 1:24:08 AM
Thanks, Mattias.

[quoted text, click to view]
AddThis Social Bookmark Button