I have created a .NET library compiled by LabVIEW which has a function that takes an array of numbers and a multiplicand. This function will return an array where each number has been multiplied with the multiplicand. When the function is called in C#, it turns out that the function takes a non-zero indexed array (double[*]
) and an int
as the parameters and return another non-zero indexed array.
I'm able to create a non-zero indexed array with C#'s Array.CreateInstance()
method. However I'm not able to pass this array into the function since the data type required is double[*]
.
From the research on the internet, it seems like .NET does not support non-zero indexed array type. I've tried to find a way to modify the LabVIEW program to generate the function that takes in a zero-indexed array without avail.
Any advice on how I can go around this issue?
Update 1
LabVIEW block diagram
C# Program
const int Length = 5;
const int LowerBound = 1;
// Instanstiate a non-zero indexed array. The array is one-dimensional and
// has size specified by Length and lower bound specified by LowerBound.
Array numbers = Array.CreateInstance(typeof(double), new int[] { Length }, new int[] { LowerBound });
// Initialize the array.
for (int i = numbers.GetLowerBound(0); i <= numbers.GetUpperBound(0); i++)
{
numbers.SetValue(i, i);
}
var variable = LabVIEWExports.Multiply(numbers, 2); // This is invalid as numbers is not typed double[*].
Console.ReadKey();
Signature of the LabVIEW function in C#
Update 2
Tried to use C#'s Reflection to call the LabVIEW function with the following codes, but encounter TargetInvocationException
.
const int Length = 5;
const int LowerBound = 1;
const string methodName = "MultiplyArray";
const string path = @"C:\";
Array numbers = Array.CreateInstance(typeof(double), new int[] { Length }, new int[] { LowerBound });
for (int i = numbers.GetLowerBound(0); i <= numbers.GetUpperBound(0); i++)
{
numbers.SetValue(i, i);
}
Assembly asm = Assembly.LoadFile(path + "LabVIEW.Interop.dll");
Type type = asm.GetType("LabVIEW.Interop.LabVIEWInteropExports");
if (type != null)
{
MethodInfo methodInfo = type.GetMethod(methodName);
if (methodInfo != null)
{
object result = methodInfo.Invoke(methodInfo, new object[] { array, multiplicand }); // Throw exception.
}
}
Console.ReadKey();
Inner exception message
Unable to cast object of type 'System.Double[*]' to type 'System.Double[]'.
Inner exception stack trace
at NationalInstruments.LabVIEW.Interop.DataMarshal.InitMarshalArrayIn(IntPtr data, Array array, Marshal1DArray val)
at LabVIEW.Interop.LabVIEWInteropExports.MultiplyArray(Double[*] input__32Array, Int32 numeric)
It seems like at some point of the execution, the program tries to marshal the type double[*]
to double[]
with InitMarshalArrayIn()
function in the assembly that comes with LabVIEW.
Zero-based array indexing is a way of numbering the items in an array such that the first item of it has an index of 0, whereas a one-based array indexed array has its first item indexed as 1. Zero-based indexing is a very common way to number items in a sequence in today's modern mathematical notation.
In computer science, array indices usually start at 0 in modern programming languages, so computer programmers might use zeroth in situations where others might use first, and so forth.
The most common answer to the array numbering question, points out that zero-based numbering comes from language design itself. In C an array points to the location in the memory, so in expression array[n], n should not be treated as an index, but as an offset from the array's head.
I'm not sure whether i should put this as answer or not, but here it goes:
It happens that this is an issue related to Visual Studio 2015 as I'm using Visual Studio Community 2015 Update 1. See this and this for more info.
.NET does support arrays that are non-zero indexes. C# has no syntax to write such a type but you can create it using Array.CreateInstance
.
Next, use reflection to call LabVIEWExports.Multiply
and pass the array that you created.
Will it work if you use dynamic
(rather than resorting to reflection), as in the last line of:
const int Length = 5;
const int LowerBound = 1;
// Instanstiate a non-zero indexed array. The array is one-dimensional and
// has size specified by Length and lower bound specified by LowerBound.
var numbers = Array.CreateInstance(typeof(double), new int[] { Length }, new int[] { LowerBound });
// Initialize the array.
for (int i = numbers.GetLowerBound(0); i <= numbers.GetUpperBound(0); i++)
{
numbers.SetValue(i, i);
}
var variable = (Array)LabVIEWExports.Multiply((dynamic)numbers, 2);
The variable numbers
has compile-time type Array
to C# since C# does not have a syntax for double[*]
. But maybe it will be OK with dynamic
where the actual type of numbers
at run-time should be correct, so maybe late binding to the correct method will work?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With