Array of structures from a COM callback.

G

Guest

Hi we have a 3rd party in process com dll, which was written In C++ and our
client is in c#.

All is working fine apart from we get a callback from the DLL which contains
an array of structures.

The callback signature looks like this,

With the list stored in the radioSubscriberAttributes3List, which is defined
in the type library which was created when we imported the com dll into .net

unsafe private void GroupManager_GetRadioSubscribersConfirmation(uint
radioSubscriberAttributes3ListSize, ref tcsRadioSubscriberAttributes3_t
radioSubscriberAttributes3List, tcsBoolean_t endOfCollection, short cookie);

trouble is we only get the first structure back, if I use the code below.

tcsRadioSubscriberAttributes3_t[] DATA = new
tcsRadioSubscriberAttributes3_t[3];
temp = Marshal.AllocCoTaskMem(IntPtr.Size);
buffer = Marshal.AllocCoTaskMem(IntPtr.Size);

//get the address in buffer
Marshal.StructureToPtr(radioSubscriberAttributes3List, buffer, true);
temp = buffer;

for(int a=0; a<radioSubscriberAttributes3ListSize; a++ )
{
DATA[a] =
(tcsRadioSubscriberAttributes3_t)Marshal.PtrToStructure(temp,radioSubscriberAttributes3List.GetType());
temp = (IntPtr)((int)buffer +
Marshal.SizeOf(radioSubscriberAttributes3List.GetType()));
}

I guess StructureToPtr copies the first item from the list passed to us,
into managed memory, and not the rest.

Any help, as if we don’t get this working we will have to write the client
in Delphi !!!!

Cheers Rich.
 
J

Jianwei Sun

Rich,

I cannot gurantee this is the right answer, but if I were you, I will
try that.

When calling Marshal.StructureToPtr, I will increment the buffer value
just as you did when calling PtrToStructure.

Something like

for(int a=0; a<radioSubscriberAttributes3ListSize; a++ )
{
IntPtr temp;
temp = IntPtr(buffer+a*size);
Marshal.StructureToPtr(radioSubscriberAttributes3List, temp, true);
}

HTH
 
G

Guest

Thanks for that, but still no luck.

I think the main problem is that we are getting the adress of the first
struture when we do StructureToPointer, but when i look in memmory at this
address i can't see any other struture data that should be on the array after
the first one.

I think the COM c++ is passing us the address of the 1st item in the array
of stuctures and not the array, so when we call StuctureToPointer we only get
1 stucture.

Jianwei Sun said:
Rich,

I cannot gurantee this is the right answer, but if I were you, I will
try that.

When calling Marshal.StructureToPtr, I will increment the buffer value
just as you did when calling PtrToStructure.

Something like

for(int a=0; a<radioSubscriberAttributes3ListSize; a++ )
{
IntPtr temp;
temp = IntPtr(buffer+a*size);
Marshal.StructureToPtr(radioSubscriberAttributes3List, temp, true);
}

HTH

Rich said:
Hi we have a 3rd party in process com dll, which was written In C++ and our
client is in c#.

All is working fine apart from we get a callback from the DLL which contains
an array of structures.

The callback signature looks like this,

With the list stored in the radioSubscriberAttributes3List, which is defined
in the type library which was created when we imported the com dll into .net

unsafe private void GroupManager_GetRadioSubscribersConfirmation(uint
radioSubscriberAttributes3ListSize, ref tcsRadioSubscriberAttributes3_t
radioSubscriberAttributes3List, tcsBoolean_t endOfCollection, short cookie);

trouble is we only get the first structure back, if I use the code below.

tcsRadioSubscriberAttributes3_t[] DATA = new
tcsRadioSubscriberAttributes3_t[3];
temp = Marshal.AllocCoTaskMem(IntPtr.Size);
buffer = Marshal.AllocCoTaskMem(IntPtr.Size);

//get the address in buffer
Marshal.StructureToPtr(radioSubscriberAttributes3List, buffer, true);
temp = buffer;

for(int a=0; a<radioSubscriberAttributes3ListSize; a++ )
{
DATA[a] =
(tcsRadioSubscriberAttributes3_t)Marshal.PtrToStructure(temp,radioSubscriberAttributes3List.GetType());
temp = (IntPtr)((int)buffer +
Marshal.SizeOf(radioSubscriberAttributes3List.GetType()));
}

I guess StructureToPtr copies the first item from the list passed to us,
into managed memory, and not the rest.

Any help, as if we don’t get this working we will have to write the client
in Delphi !!!!

Cheers Rich.
 
M

Mattias Sjögren

Rich,
With the list stored in the radioSubscriberAttributes3List, which is defined
in the type library which was created when we imported the com dll into .net

unsafe private void GroupManager_GetRadioSubscribersConfirmation(uint
radioSubscriberAttributes3ListSize, ref tcsRadioSubscriberAttributes3_t
radioSubscriberAttributes3List, tcsBoolean_t endOfCollection, short cookie);

trouble is we only get the first structure back, if I use the code below.

And that's all you're going to get as long as the parameter is
declared as "ref tcsRadioSubscriberAttributes3_t". You'll have to
change that to a real array or an IntPtr by modifying the interop
assembly. How to do that is explained in

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


Mattias
 
G

Guest

Made the changes and it works fine.

another question is this pointing to managed or unmanaged code, i guess
managed as i didnt have to decare the code as unsafe.

Cheers Rich.
 
M

Mattias Sjögren

Rich,
another question is this pointing to managed or unmanaged code, i guess
managed as i didnt have to decare the code as unsafe.

You mean the IntPtr? It's a pointer to the _memory_ (not code) where
the caller allocated the structs. Since the caller is a native C++
library it's most likely not the managed heap, but rather a native
heap or stack.


Mattias
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top