Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-zero indexed array

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 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#

enter image description here

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.

like image 720
Noctis Tong Avatar asked Feb 18 '16 09:02

Noctis Tong


People also ask

What is meant by zero indexed array?

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.

Are arrays always indexed from 0?

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.

Why are arrays zero indexed?

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.


Video Answer


3 Answers

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.

like image 163
Noctis Tong Avatar answered Oct 13 '22 01:10

Noctis Tong


.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.

like image 20
usr Avatar answered Oct 12 '22 23:10

usr


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?

like image 32
Jeppe Stig Nielsen Avatar answered Oct 13 '22 00:10

Jeppe Stig Nielsen