Bishal Bansal

Hi

I have created a DLL in C# and using the same in VC++ using COM interop. However i need to pass an array of user defined structures to VC++. The signature of the IDL File shows the return type of an array element as SAFEARRAY. I am able to get the elements from the SAFEARRAY but not able to get the exact values. Am i missing something
Please help

VC++ code


hr = CoInitialize(NULL);

ReaderXML::ISampleXMLSerializeDemoPtr

xmlSerializerptr(__uuidof(SampleXMLSerializerDemo));

IEmployeePtr emp(__uuidof(Employee));

struct IEmployee *_result;

if (SUCCEEDED(hr))
{

HRESULT hr= xmlSerializerptr->ConvertXMLToEmployee();
if(SUCCEEDED(hr))

xmlSerializerptr->raw_GetEmployeeDetails(&_result); //_result will have the Employee object

//returned from C# dll

}


long lIndex =0;
long pinCode=0;
SAFEARRAY *pSa;
pSa= _result->GetEmpAddress(); //GetEmpAddress returns an array of Address objects

Address HUGEP *pAddressList= NULL;


//Problem in the following part .. i am getting value for pinCode but not what is being received from the dll


hr = SafeArrayAccessData(pSa,(void HUGEP**) &pAddressList);

if(hr == S_OK)
{
for (lIndex =0; lIndex < pSa->rgsabound[0].cElements; lIndex++ )
{

pinCode = (long)pAddressList[lIndex].PinCode; //Pincode is something like 17629104 instead of 100

}
}

SafeArrayUnaccessData(pSa);




//C# Code


public interface IAddress
{
int PinCode { get; set; }
}

[ClassInterface(ClassInterfaceType.None)]
[StructLayout(LayoutKind.Sequential)]
[Serializable]

public class Address:IAddress //ADDRESS CLASS
{
private int pinCode;

public int PinCode
{
get { return pinCode; }
set { pinCode = value; }
}
public Address()
{

}


}


public interface IEmployee
{
string Name { get; set; }
Address[] EmpAddress { get; set; }
int Age { get;set; }
}
[ClassInterface(ClassInterfaceType.None)]
[Serializable]
public class Employee : IEmployee
{
private string name;
private Address[] address;
private int age;


[System.Xml.Serialization.XmlElementAttribute("EmpAddress")] //this attribute is required for accessing an array
public Address[] EmpAddress
{
get { return this.address ; }
set { this.address = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public Employee()
{
address = new Address[5];
age = 0;
name = "";
}

public Employee(Employee e)
{
this.age = e.Age;
this.name = e.Name;
this.address = e.EmpAddress;
}

}





public class SampleXMLSerializerDemo:ISampleXMLSerializeDemo
{

Employee emp;


public Employee GetEmployeeDetails()
{
return emp;
}


public void ConvertXMLToEmployee()
{
try
{

Employee e = new Employee();
e.Age = 2;
e.Name = "Hello";

Address []addr = new Address[2];
addr[0].PinCode = 100;
addr[1].PinCode = 111;
e.EmpAddress = addr;

emp = e;

}
catch (Exception ex)
{
throw ex;
}

}
public SampleXMLSerializerDemo()
{
}
}


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->



Re: Common Language Runtime COM interoperability- SAFEARRAY usage

nobugz

You are treating AddressList as though it is a array of structures. It isn't, it's an array of IAddress pointers. You'll have to call the property getter of the IAddress interface pointer to obtain the value of the PinCode property. Technically, you should call QueryInterface to obtain the IAddress interface pointer.





Re: Common Language Runtime COM interoperability- SAFEARRAY usage

Bansal






Re: Common Language Runtime COM interoperability- SAFEARRAY usage

Bansal

Hi ,
Thanks for the reply.
When i access using the property getter

pAddressList[lIndex]->GetPinCode();

then i am getting error as

'ReaderXML::Address' does not have an overloaded member 'operator ->'.

Can u please suggest where i am wrong. A small example from scratch would be very helpful.




Re: Common Language Runtime COM interoperability- SAFEARRAY usage

nobugz

Your declaration for pAddressList is wrong. It should be something like this:

IUnknown* HUGEP pAddressList = NULL;

Then use QueryInterface() to obtain the IAddress pointer. If you declared "Address" in your C/C++ code, be sure to remove it. All declarations must come from the type library.





Re: Common Language Runtime COM interoperability- SAFEARRAY usage

Bishal Bansal

Thanks for the reply.
Even when I take the pAddressList as array IUnknown/IAddress then also i am not able to get the values.
I am using Get Accessor methods to reference the members. Also all declarations are coming from TypeLib only.
No compilation error but durin runtime the memory access violation happens


IUnknown HUGEP *pEmployeeList= NULL;
//
IEmployee HUGEP *pEmployeeList= NULL;

IEmployee* pEmployee;

hr = SafeArrayAccessData(pSa1,(void HUGEP**) &pEmployeeList);

if(SUCCEEDED(hr))
{

hr = pEmployeeList->QueryInterface(__uuidof(IEmployee),(void**)&pEmployee); //Access violation error

}


Can you pls look help as to what and where i am missing Also do i need to marshal individual members of the Employee class.