We have a C#/.Net COM server (COM-visible assembly) with the following interface & class declarations:
[ComVisible(true)]
[Guid( "..." )]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITest
{
void TestMethod( [In] int nNumElements,
[In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] byte [] bArray );
}
[ComVisible(true)]
[Guid( "..." )]
[ClassInterface( ClassInterfaceType.None )]
[ProgId( "CSCOMServer.CSTest" )]
public class CSTest : ITest
{
public void TestMethod( int nNumElements, byte [] bArray )
{
for (int i = 0; i < bArray.Length; i++)
{
bArray [i] = (byte)i;
}
}
}
The resulting IDL/typelib is:
...
interface ITest : IUnknown {
HRESULT _stdcall TestMethod(
[in] long nNumElements,
[in, out] unsigned char* bArray);
};
...
coclass CSTest {
interface _Object;
[default] interface ITest;
};
The goal is to be able to utilize this from a C++ COM client, which works fine using the following:
int iSize = 10;
ITest *test;
byte *buf = (byte*)CoTaskMemAlloc( iSize * sizeof(byte) );
CoCreateInstance( CLSID_CSTest, NULL, CLSCTX_INPROC_SERVER, IID_ITest, (void **) &test );
test->TestMethod( iSize, buf );
The buffer is allocated by C++ and passed to C# for population.
All works well and upon the completion of TestMethod() the C++ array (buf) contains correct values set by the C# method.
The question is about efficiency:
Does the Interop wrapper perform array copying during marshaling (“In” phase) and then back (“Out” phase) OR does the C# method operate directly on the passed in memory (which may be pinned)?
No, a copy is definitely required here since you ask for a structural change. The CLR must create a managed array object to meet the byte[] argument type requirement. And the source array isn’t in any way usable as-is since it is nothing but a raw chunk of memory. The other way around (byte[] to unsigned char*) can work but that’s not the case here.
The normal COM automation type for arrays is SAFEARRAY btw, no speed advantage but there are a lot more COM clients that could use your server.