M
Mike Stoker
I'm trying to use an existing COM object from within .NET
and am having problems passing a parameter than used to
be of type VARIANT.
I have a COM interface, IScanner with the following
method:
virtual HRESULT __stdcall GetOptionDetails (
/*[in]*/ long lOption,
/*[in,out]*/ VARIANT * pVarBuffer,
/*[out,retval]*/ long * plResult );
where the variant, pVarBuffer, will contain one of a
variety of structures, including:
struct IMAGE_OPTION_DETAILS
{
long lSequenceNumber;
long lGreyScaleSupported;
long lVResolution;
long lHResolution;
long lBitDepth;
};
The following code shows how the structure was previously
converted to a variant and passed to the interface:
void GetUdtRecordInfo(const TCHAR *tszName, IRecordInfo**
ppRecInfo)
{
// Use Macro for easier unicode conversion
USES_CONVERSION;
ITypeLib FAR* pITypeLib;
ITypeInfo FAR* pITypeInfo;
HRESULT hr = LoadRegTypeLib(LIBID_PSCLASSICLib,
1, 0,
GetUserDefaultLCID
(), &pITypeLib);
if (hr != S_OK)
THROW_ERROR("Failed to load type
library");
// Retreive the IRecordInfo from the ITypeInfo
interface for the first (and only) occurance
// of the type in the type library
USHORT nFound = 1; // number of occurances
to look for
MEMBERID mID[1]; // array to store the
MEMBERID of the type. Must be same size as nFound
hr = pITypeLib->FindName(T2OLE(tszName), 0,
&pITypeInfo, mID, &nFound);
if (hr != S_OK)
THROW_ERROR("Failed to find the name of
UDT.");
hr = GetRecordInfoFromTypeInfo(pITypeInfo,
ppRecInfo);
if (hr != S_OK)
THROW_ERROR("Failed to get the Record
Info of UDT");
// Release interfaces
pITypeInfo->Release();
pITypeLib->Release();
}
void ConstructRecordVariant(IRecordInfo* pRecInfo,
LPVARIANT pVariant, void* pStruct)
{
VariantInit(pVariant);
V_VT(pVariant) = VT_RECORD | VT_BYREF;
V_RECORD(pVariant) = pStruct;
pVariant->pRecInfo = pRecInfo;
}
int _tmain()
{
IMAGE_OPTION_DETAILS details;
VARIANT var;
IRecordInfo* pRecordInfo = NULL;
CString sTypeName = "IMAGE_OPTION_DETAILS";
void* pStruct = &details;
// Construct the VARIANT data structures for the
detail, in and out data.
GetUdtRecordInfo(sTypeName, &pRecordInfo);
ConstructRecordVariant(pRecordInfo, &var,
pStruct);
// now we make the call to the COM interface
HRESULT = pIScanner->GetOptionDetails
(IMAGE_FRONT, &var);
return 0;
}
In DotNet, the COM object is wrapped into a class with
the above method converted to:
public int GetOptionDetails(int lOption, ref object
pVarBuffer);
My question is how do I pass the converted version of the
above structure to this method? I tried the obvious
ScannerClass * scanner = new ScannerClass();
IMAGE_OPTION_DETAILS details;
Object* obj = __box(details);
scanner->GetOptionDetails(
SCANNER_OPTIONS::IMAGE_FRONT,
&obj);
but this failed with:
"A first chance exception of
type 'System.ArgumentException' occurred in PSTest.exe"
"Additional information: The specified record cannot be
mapped to a managed value class."
Any help would be much appreciated!
Mike.
and am having problems passing a parameter than used to
be of type VARIANT.
I have a COM interface, IScanner with the following
method:
virtual HRESULT __stdcall GetOptionDetails (
/*[in]*/ long lOption,
/*[in,out]*/ VARIANT * pVarBuffer,
/*[out,retval]*/ long * plResult );
where the variant, pVarBuffer, will contain one of a
variety of structures, including:
struct IMAGE_OPTION_DETAILS
{
long lSequenceNumber;
long lGreyScaleSupported;
long lVResolution;
long lHResolution;
long lBitDepth;
};
The following code shows how the structure was previously
converted to a variant and passed to the interface:
void GetUdtRecordInfo(const TCHAR *tszName, IRecordInfo**
ppRecInfo)
{
// Use Macro for easier unicode conversion
USES_CONVERSION;
ITypeLib FAR* pITypeLib;
ITypeInfo FAR* pITypeInfo;
HRESULT hr = LoadRegTypeLib(LIBID_PSCLASSICLib,
1, 0,
GetUserDefaultLCID
(), &pITypeLib);
if (hr != S_OK)
THROW_ERROR("Failed to load type
library");
// Retreive the IRecordInfo from the ITypeInfo
interface for the first (and only) occurance
// of the type in the type library
USHORT nFound = 1; // number of occurances
to look for
MEMBERID mID[1]; // array to store the
MEMBERID of the type. Must be same size as nFound
hr = pITypeLib->FindName(T2OLE(tszName), 0,
&pITypeInfo, mID, &nFound);
if (hr != S_OK)
THROW_ERROR("Failed to find the name of
UDT.");
hr = GetRecordInfoFromTypeInfo(pITypeInfo,
ppRecInfo);
if (hr != S_OK)
THROW_ERROR("Failed to get the Record
Info of UDT");
// Release interfaces
pITypeInfo->Release();
pITypeLib->Release();
}
void ConstructRecordVariant(IRecordInfo* pRecInfo,
LPVARIANT pVariant, void* pStruct)
{
VariantInit(pVariant);
V_VT(pVariant) = VT_RECORD | VT_BYREF;
V_RECORD(pVariant) = pStruct;
pVariant->pRecInfo = pRecInfo;
}
int _tmain()
{
IMAGE_OPTION_DETAILS details;
VARIANT var;
IRecordInfo* pRecordInfo = NULL;
CString sTypeName = "IMAGE_OPTION_DETAILS";
void* pStruct = &details;
// Construct the VARIANT data structures for the
detail, in and out data.
GetUdtRecordInfo(sTypeName, &pRecordInfo);
ConstructRecordVariant(pRecordInfo, &var,
pStruct);
// now we make the call to the COM interface
HRESULT = pIScanner->GetOptionDetails
(IMAGE_FRONT, &var);
return 0;
}
In DotNet, the COM object is wrapped into a class with
the above method converted to:
public int GetOptionDetails(int lOption, ref object
pVarBuffer);
My question is how do I pass the converted version of the
above structure to this method? I tried the obvious
ScannerClass * scanner = new ScannerClass();
IMAGE_OPTION_DETAILS details;
Object* obj = __box(details);
scanner->GetOptionDetails(
SCANNER_OPTIONS::IMAGE_FRONT,
&obj);
but this failed with:
"A first chance exception of
type 'System.ArgumentException' occurred in PSTest.exe"
"Additional information: The specified record cannot be
mapped to a managed value class."
Any help would be much appreciated!
Mike.