C# and Delphi code have different behaviour when importing unmanaged dll

231 views Asked by At

I am solving sparse system of linear equations with Math.Net Numerics in C#. I'm trying to export this code to dll (using Robert Giesecke's Unmanaged Exports) and run it from Delphi code.

Here is my C# code:

namespace MathNetSolverLib
{
    public class ParticleInterpolator
    {
        public ParticleInterpolator(int eqnumber)
        {
            n = eqnumber;
            b = Vector.Build.DenseOfArray(new double[eqnumber]);
            result = Vector.Build.DenseOfArray(new double[eqnumber]);
            input_points = new List<Tuple<int, int, double>>();
        }

        public void solve()
        {
            using (var writer = new StreamWriter("C:\\users\\s\\desktop\\logb.txt"))
            {
                for (int i = 0; i < n; ++i)
                {
                    writer.WriteLine(b[i]);
                }
            }
            using (var writer = new StreamWriter("C:\\users\\s\\desktop\\loginput.txt"))
            {
                for (int i = 0; i < input_points.Count(); ++i)
                {
                    writer.WriteLine(input_points[i]);
                }
            }

            TFQMR solver = new TFQMR();

            MathNet.Numerics.LinearAlgebra.Solvers.Iterator<double> iter = 
                new MathNet.Numerics.LinearAlgebra.Solvers.Iterator<double>();

            SparseMatrix sd = SparseMatrix.OfIndexed(n, n, input_points);
            solver.Solve(sd, b, result, iter, new DiagonalPreconditioner());



            using (var writer = new StreamWriter("C:\\users\\s\\desktop\\logres.txt"))
            {
                for (int i = 0; i < n; ++i)
                {
                    writer.WriteLine(result[i]);
                }
            }

        }
        public int n;
        public List<Tuple<int, int, double>> input_points;
        public Vector<double> result;
        public Vector<double> b;
    }

    public class Class1
    {
        [DllExport]
        public static ParticleInterpolator create(int eqnumber)
        {           
            return new ParticleInterpolator(eqnumber);
        }

        [DllExport]
        public static void addValue(int row, int col, double value, ParticleInterpolator ins)
        {
            ins.input_points.Add(new Tuple<int, int, double>(row, col, value));
        }

        [DllExport]
        public static void setRhs(int row, double value, ParticleInterpolator ins)
        {
            ins.b[row] = value;
        }

        [DllExport]
        public static void solve(ParticleInterpolator ins)
        {      
            ins.solve();
        }

        [DllExport]
        public static double getSolutionByIndex(int index, ParticleInterpolator ins)
        {
            return ins.result[index];
        }
    }
}

I have imported this to C# dll like this:

 [DllImport("MathNetSolverLib.dll", EntryPoint = "create")]
        public static extern int create(int eqnumber);

        [DllImport("MathNetSolverLib.dll", EntryPoint = "addValue")]
        public static extern void addValue(int row, int col, double value, int ins);

        [DllImport("MathNetSolverLib.dll", EntryPoint = "setRhs")]
        public static extern void setRhs(int row, double value, int ins);

        [DllImport("MathNetSolverLib.dll", EntryPoint = "solve")]
        public static extern void solve(int ins);

        [DllImport("MathNetSolverLib.dll", EntryPoint = "getSolutionByIndex")]
        public static extern double getSolutionByIndex(int index, int ins);

and it works fine.

But when I am trying to import this in Delphi:

function create(n: integer): pointer; stdcall; external MathNetSolverLib;
procedure addValue(row, col: Integer; value:double; p:pointer); stdcall; external MathNetSolverLib;
procedure setRhs(row: Integer; value: double; p:pointer); stdcall; external MathNetSolverLib;
procedure solve(p: pointer); stdcall; external MathNetSolverLib;
function getSolutionByIndex(index: Integer; p:pointer): double; stdcall; external MathNetSolverLib;

the TFQMR solver returns wrong result. It seems that algorithm inside TFQMR has different behaviour.

It is very strange because all input data (variables A, b, n and input_points) are remain the same when calling dll from C# or Delphi (I have checked it).

Does anyone have an idea how to explain this?

0

There are 0 answers