0

I am trying to create a wrapper to treat System.Numeric.Complex array as array of double, i.e. to treat {{1,2},{3,4},{5,6},{7,8} as {1,2,3,4,5,6,7,8}. I use these arrays for FFT so this way will be more efficient because avoids copying and iterating huge arrays. But i stuck on a strange chimeric monster: A Double array object of kind double[] {System.Numerics.Complex[4], instead of double[8]!!. What's that?

I am not an interop expert so excuse any essential blunder; I read some related stuff here and here and I wonder if the case is that these arrays are overlapped. Τhis code almost works except for that it returns half of the values:

 //using System.Runtime.InteropServices;
 //using System.Numeric;

    [StructLayout(LayoutKind.Explicit)]
    public struct ComplexArray2serialWrapper
    {
        [FieldOffset(0)] private Complex[] ComplexArray;
        [FieldOffset(0)] private double[] DoubleArray;

        public ComplexArray2serialWrapper(Complex[] NewcomplexArray) : this() { ComplexArray = NewcomplexArray; }
        public ComplexArray2serialWrapper(double[] NewSerialComplexArray) : this() { DoubleArray = NewSerialComplexArray; }
        public static implicit operator double[] (ComplexArray2serialWrapper source) { return source.DoubleArray; }
    }


    public static void TestWrapper()
    {
        Complex[] cc = { new Complex(1, 2), new Complex(3, 4), new Complex(5, 6), new Complex(7, 8) };  
        double[] DoubleComplexChimeraMonster = new ComplexArray2serialWrapper(cc);
        var parenttype = DoubleComplexChimeraMonster.GetType(); // result = System.Numerics.Complex[]
        //!!! but in watch window type shown as=  double[] {System.Numerics.Complex[4]}

        var ChildrenType = DoubleComplexChimeraMonster[0].GetType(); //System.Double
        //In Watch window, children types shown chimeric:        
        //{ (1, 2)} Double {System.Numerics.Complex} 
        //{ (3, 4)} Double {System.Numerics.Complex} 
        //{ (5, 6)} Double {System.Numerics.Complex} 
        //{ (7, 8)} Double {System.Numerics.Complex}

        double i1 = DoubleComplexChimeraMonster[0]; //=1 (as expected)
        double i2 = DoubleComplexChimeraMonster[1]; //=2 (as expected)
        double i3 = DoubleComplexChimeraMonster[2]; //=3 (as expected)
        double i4 = DoubleComplexChimeraMonster[3]; //=4 (as expected)
        var l = DoubleComplexChimeraMonster.Length; //=4 (8 expected)


        //So trying to get i5-i8 will throw an exception e.g.:
        //DoubleComplexChimeraMonster(4)  --> exception (5 expected)

    }
1
  • 1
    You declared a union. Not directly supported by C# because they are so notoriously type-unsafe but it won't stop you from using these CLR attributes. You managed to overlap the array elements just fine but you can't duck the field that stores the Length. It is 4, not 8. Only other thing you can do is write truly unsafe code and use a pointer so there won't be any bounds checks. Use the fixed keyword to get a Complex* and cast it with (double*). Commented Oct 23, 2017 at 13:26

1 Answer 1

1

You expect the arrays to store only the doubles. But they also store the array length and a reference to a type descriptor. Therefore, your approach of overlapping two .NET types does not work. C# is not C.

DoubleComplexChimeraMonster is statically typed as double[], however GetType() retrieves the runtime type, which happens to be Complex[].

Overlapping values at the same memory location works for primitive value types. But System.Array is a class.

As Marc Gravell says in this answer of the link you provided, unsafe pointers might be the way to go.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes i show it, but I want to use it in a VB application so I also want to keep it safe ... from pointers.
Interop is for inter-operation between COM and .NET applications. It is not a feature to be used in C# regularly and is not any better than unsafe pointers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.