Passing SAFEARRAY of Structure between ATL/COM - C#

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
I tried to pass SAFEARRAY of structures from C# - ATL/COM. I didnt have a success. Can anybody tell me, what am I missing in the code? or it is not possible?
<pre class="prettyprint // testATLCOMSvr.idl : IDL source for testATLCOMSvr
//
// This file will be processed by the MIDL tool to
// produce the type library (testATLCOMSvr.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(),
oleautomation,
nonextensible,
pointer_default(unique)
]
interface IATLTest : IUnknown{

typedef
[
uuid(),
version(1.0),
helpstring("safe arrary")
]
struct MG_ACQU_CHANNEL_T
{
BSTR strChannelName; //ecm channels class props
}MG_ACQU_CHANNEL_T;

[id(1), helpstring("get atl string"), helpcontext(1)] HRESULT GetATLString2([in] BSTR myString, [out,retval] BSTR* retVal);
[id(2), helpstring("safearray"), helpcontext(2)] HRESULT GetSafeArrayOfParam([in] SAFEARRAY(MG_ACQU_CHANNEL_T) ChannelList, [out,retval] BSTR* retVal);
};
[
uuid(),
version(1.0),
]
library testATLCOMSvrLib
{
importlib("stdole2.tlb");
[
uuid()
]
coclass ATLTest
{
[default] interface IATLTest;
};
};
ATLTest.h
// ATLTest.h : Declaration of the CATLTest
#pragma once
#include "resource.h" // main symbols
#include "testATLCOMSvr_i.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM objects and allow use of its single-threaded COM object implementations. The threading model in your rgs file was set to Free as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
using namespace ATL;
// CATLTest
class ATL_NO_VTABLE CATLTest :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CATLTest, &CLSID_ATLTest>,
public IATLTest
{
public:
CATLTest()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_ATLTEST)
DECLARE_NOT_AGGREGATABLE(CATLTest)
BEGIN_COM_MAP(CATLTest)
COM_INTERFACE_ENTRY(IATLTest)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:

STDMETHOD(GetATLString2)(BSTR myString, BSTR* retVal);
STDMETHOD(GetSafeArrayOfParam)(SAFEARRAY * ChannelList, BSTR* retVal);
};
OBJECT_ENTRY_AUTO(__uuidof(ATLTest), CATLTest)
ATLTest.cpp
// ATLTest.cpp : Implementation of CATLTest
#include "stdafx.h"
#include "ATLTest.h"
// CATLTest
STDMETHODIMP CATLTest::GetATLString2(BSTR myString, BSTR* retVal)
{
// TODO: Add your implementation code here
return S_OK;
}
STDMETHODIMP CATLTest::GetSafeArrayOfParam(SAFEARRAY * ChannelList, BSTR* retVal)
{
// TODO: Add your implementation code here

return S_OK;
}
C# - ATLClient
Array arr = Array.CreateInstance(typeof(MG_ACQU_CHANNEL_T), 2);

for (int i = 0; i < 2; i++)
{
MG_ACQU_CHANNEL_T channel = new MG_ACQU_CHANNEL_T();
channel.strChannelName = "welcome " + i;
arr.SetValue(channel, i);
}

IATLTest atlTest = new ATLTest();
try
{
string str = "test string";

atlTest.GetATLString2(str);
atlTest.GetSafeArrayOfParam(arr);
}
catch (ArgumentException ae)
{

}
When I right click on function “GetSafeArrayOfParam “ and go to function definition in c#. I see below function definition.
using System;
using System.Runtime.InteropServices;
namespace testATLCOMSvrLib
{
[TypeLibType(384)]
[Guid()]
[InterfaceType(1)]
public interface IATLTest
{
string GetATLString2(string myString);
string GetSafeArrayOfParam(Array ChannelList); //structure showed as array in C#
}
}[/code]
When I run the code, I get an exception:
Exception:<br/>
System.ArgumentException was caught<br/>
Message=The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))<br/>
Source=mscorlib<br/>
StackTrace:<br/>
at System.StubHelpers.MngdSafeArrayMarshaler.ConvertSpaceToNative(IntPtr pMarshalState, Object& pManagedHome, IntPtr pNativeHome)<br/>
at testATLCOMSvrLib.IATLTest.GetSafeArrayOfParam(Array ChannelList)<br/>
at ATLClient.Form1.Form1_Load(Object sender, EventArgs e) in ATLClientForm1.cs:line 51<br/>
InnerException:

Thanks in advance.
<br/>

View the full article
 
Back
Top