G
Guest
I’ve got a C# library that I’ve built into a COM component that will be used
from a VC++ 6 application and while the creation of the COM object side of
things seem to be working fine, using the object fully is another matter.
On the C# side of things I’ve got an object defined like so:
[ClassInterface(ClassInterfaceType.None)]
public class PID : IPID
{
private string type;
private int number;
private PID[] pids;
public string Type
{
get { return type;}
set { type = value;}
}
public int Number
{
get { return number;}
set { number = value;}
}
public PID[] PIDs
{
get { return pids;}
set { pids = value;}
}
public PID(){}
public PID(string type, int number)
{
this.type = type;
this.number = number;
this.pids = new PID[0];
}
public PID(string type, int number, PID[] pids)
{
this.type = type;
this.number = number;
this.pids = pids;
}
}
I can instantiate an instance of this object in the MFC app with no
problem... the problem is when I try to set the PIDs array to... anything but
null really.
The issue is that the C# array is viewed by the MFC app as pointer to a
SAFEARRAY and all attempts to create an array of PID objects and assign them
to the PIDs property fails.
I’ve tried straight up (and cheesy) typecasting:
IPIDPtr pPID1(__uuidof(PID));
IPID *pid1 = pPID1;
....
IPID *pidArray1[2];
pidArray1[0] = pid2;
pidArray1[1] = pid3;
pid1->PIDs = (SAFEARRAY*)pidArray1;
Which causes a friendly “User breakpoint called from code at 0x7c901230†and
points to code I do not have the debug symbols for.
I also tried explicitly creating a SAFEARRAY with SafeArrayCreate:
SAFEARRAY * psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 2;
psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
LONG index = 0;
SafeArrayPutElement(psa, &index, &pid2);
index = 1;
SafeArrayPutElement(psa, &index, &pid3);
fi->PIDs = psa;
In this example everything works fine up until we assign PIDs (but not when
we set PIDs to null)... then we get an exception which reads:
Unhandled exception at 0x7c81eb33 in MFCWSTestApp.exe: Microsoft C++
exception: _com_error @ 0x0012f8c4.
When the following line is called from the .tli wrapper:
inline void IFileInformation:utPIDs ( SAFEARRAY * _arg1 ) {
_com_dispatch_method(this, 0x60020004, DISPATCH_PROPERTYPUT,
VT_EMPTY, NULL,
L"\x2009", _arg1);
}
Thinking that I should be a little more explicit with regards to the size of
the elements (and based on another example) I tried the following:
SAFEARRAY *params = SafeArrayCreateVector(VT_R4, 0, 2);
int paramMin = 0;
SafeArrayAccessData(params, (void**)&pid1);
memcpy(¶mMin, &pid1, sizeof(IPID));
SafeArrayUnaccessData(params);
paramMin = 1;
SafeArrayAccessData(params, (void**)&pid2);
memcpy(¶mMin, &pid2, sizeof(PID));
SafeArrayUnaccessData(params);
This test behaves similarly to the previous one in that the bulk of the code
executes without any error... but then an unhandled exception is thrown the
moment we try to assign PIDs to anything... including null:
Unhandled exception at 0x7c81eb33 in MFCWSTestApp.exe: Microsoft C++
exception: _com_error @ 0x0012f894.
Because of the far easier to use environment and debugger I have spent a
fair amount of time trying to resolve this issue within the VC7.1
environment, unfortunately both VC6 and VC7 have the exact same issues with
the code in question.
Aside from the obvious issue of trying to use VC6... does anyone see what I
might be doing wrong here or have any ideas on how I could fix it?
from a VC++ 6 application and while the creation of the COM object side of
things seem to be working fine, using the object fully is another matter.
On the C# side of things I’ve got an object defined like so:
[ClassInterface(ClassInterfaceType.None)]
public class PID : IPID
{
private string type;
private int number;
private PID[] pids;
public string Type
{
get { return type;}
set { type = value;}
}
public int Number
{
get { return number;}
set { number = value;}
}
public PID[] PIDs
{
get { return pids;}
set { pids = value;}
}
public PID(){}
public PID(string type, int number)
{
this.type = type;
this.number = number;
this.pids = new PID[0];
}
public PID(string type, int number, PID[] pids)
{
this.type = type;
this.number = number;
this.pids = pids;
}
}
I can instantiate an instance of this object in the MFC app with no
problem... the problem is when I try to set the PIDs array to... anything but
null really.
The issue is that the C# array is viewed by the MFC app as pointer to a
SAFEARRAY and all attempts to create an array of PID objects and assign them
to the PIDs property fails.
I’ve tried straight up (and cheesy) typecasting:
IPIDPtr pPID1(__uuidof(PID));
IPID *pid1 = pPID1;
....
IPID *pidArray1[2];
pidArray1[0] = pid2;
pidArray1[1] = pid3;
pid1->PIDs = (SAFEARRAY*)pidArray1;
Which causes a friendly “User breakpoint called from code at 0x7c901230†and
points to code I do not have the debug symbols for.
I also tried explicitly creating a SAFEARRAY with SafeArrayCreate:
SAFEARRAY * psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 2;
psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
LONG index = 0;
SafeArrayPutElement(psa, &index, &pid2);
index = 1;
SafeArrayPutElement(psa, &index, &pid3);
fi->PIDs = psa;
In this example everything works fine up until we assign PIDs (but not when
we set PIDs to null)... then we get an exception which reads:
Unhandled exception at 0x7c81eb33 in MFCWSTestApp.exe: Microsoft C++
exception: _com_error @ 0x0012f8c4.
When the following line is called from the .tli wrapper:
inline void IFileInformation:utPIDs ( SAFEARRAY * _arg1 ) {
_com_dispatch_method(this, 0x60020004, DISPATCH_PROPERTYPUT,
VT_EMPTY, NULL,
L"\x2009", _arg1);
}
Thinking that I should be a little more explicit with regards to the size of
the elements (and based on another example) I tried the following:
SAFEARRAY *params = SafeArrayCreateVector(VT_R4, 0, 2);
int paramMin = 0;
SafeArrayAccessData(params, (void**)&pid1);
memcpy(¶mMin, &pid1, sizeof(IPID));
SafeArrayUnaccessData(params);
paramMin = 1;
SafeArrayAccessData(params, (void**)&pid2);
memcpy(¶mMin, &pid2, sizeof(PID));
SafeArrayUnaccessData(params);
This test behaves similarly to the previous one in that the bulk of the code
executes without any error... but then an unhandled exception is thrown the
moment we try to assign PIDs to anything... including null:
Unhandled exception at 0x7c81eb33 in MFCWSTestApp.exe: Microsoft C++
exception: _com_error @ 0x0012f894.
Because of the far easier to use environment and debugger I have spent a
fair amount of time trying to resolve this issue within the VC7.1
environment, unfortunately both VC6 and VC7 have the exact same issues with
the code in question.
Aside from the obvious issue of trying to use VC6... does anyone see what I
might be doing wrong here or have any ideas on how I could fix it?