A number of people have asked me about passing arrays to .NET functions from Visual FoxPro applications. The problem here is that Visual FoxPro arrays are not formatted the right way to just be called to a .NET COM object by default. VFP arrays are 1 based while in general COM objects expect arrays to be 0 based so you need to fix up arrays to make this happen. .NET arrays are always 0 based unless explicitly declared otherwise.
Assume you have a method in a .NET COM object that looks like this:
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("DotNetCom.DotNetComPublisher")]
public class DotNetComPublisher
public string PassArray(object[] Objects )
{
string Output = "";
foreach(object Customer in Objects)
{
// *** Must access array by using Reflection
Output += ComUtils.GetProperty(Customer,"Name") + " " +
ComUtils.GetProperty(Customer,"Name") + "\r\n";
}
return Output;
}
}
And you want to pass an object like this:
loAddr = CREATEOBJECT("EMPTY")
ADDPROPERTY(loAddr,"Name","Rick Strahl")
ADDPROPERTY(loAddr,"Company","West Wind")
ADDPROPERTY(loAddr,"Date",DATETIME())
loAddr2 = CREATEOBJECT("EMPTY")
ADDPROPERTY(loAddr2,"Name","Rick Strahl")
ADDPROPERTY(loAddr2,"Company","West Wind")
ADDPROPERTY(loAddr2,"Date",DATETIME())
DIMENSION loAddrArray[2]
loAddrArray[1] = loAddr
loAddrArray[2] = loAddr2
To .NET. Your first try likely looks like this:
LOCAL loNet as DotNetCom.DotNetComPublisher
loNet = CREATEOBJECT('DotNetCom.DotNetComPublisher')
? loNet.PassArray(@loAddrArray)
which will fail with Invalid Parameter type.
The key to make this work is to use the COMARRAY() function in VFP to mark the array as 0 based and passed by reference:
LOCAL loNet as DotNetCom.DotNetComPublisher
loNet = CREATEOBJECT('DotNetCom.DotNetComPublisher')
COMARRAY(loNet,10)
? loNet.PassArray(@loAddrArray)
And this works correctly passing the objects to .NET.
To return arrays works as well. Take the following .NET method:
public Customer[] ReturnArray(int Count)
{
Customer[] Customers = new Customer[Count];
for (int x=0; x < Count; x++)
{
Customers[x] = new Customer();
Customers[x].Company = "West Wind " + DateTime.Now.ToString();
Customers[x].oAddress.StreetAddress = DateTime.Now.ToString();
}
return Customers;
}
Which you can retrieve like this in FoxPro:
LOCAL loNet as DotNetCom.DotNetComPublisher
loNet = CREATEOBJECT('DotNetCom.DotNetComPublisher')
loArray =loNet.ReturnArray(3)
lnCount = ALEN(loArray,1)
FOR x=1 TO lnCount
loCust = loArray[x]
? loCust.Company
? loCust.oAddress.StreetAddress
ENDFOR
RETURN
Note that you are not getting the Array object that .NET is returning. There’s no Length property for example, but rather VFP marshals this .NET array to a standard array. Actually .NET returns this array to COM as a COM compatible SafeArray and VFP picks that up and exposes the array as a VFP array object. You won't need to use COMARRAY() on the returned array.
A final option that I like to use in many situations is to not pass arrays as parameter or return types directly, but rather pass objects that contain arrays. The advantage is that you get more control over the data and you have a chance to potentially call COMARRAY() with other marshalling options.
Other Posts you might also like