Mark
Mark

Reputation: 108512

P/Invoke Struct with Pointers, C++ from C#

I'm attempt to call a C++ dll with a struct and function like

struct some_data{
  int size,degree,df,order;
  double *x,*y,lambda;
};

extern "C"{    
   __declspec(dllexport) double *some_func(some_data*);
}

from C#:

  [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct SOME_DATA
    {
        public int size;
        public int degree;
        public int df;
        public int order;
        public System.IntPtr x;
        public System.IntPtr y;
        public double lambda;
    }

    [System.Runtime.InteropServices.DllImportAttribute("mydll.dll",EntryPoint="some_func")]
    public static extern System.IntPtr some_func(ref SOME_DATA someData);

    public IntPtr some_funcCall(){
        double[] x = new double[] { 4, 4, 7, 7 };
        double[] y = new double[] { 2, 10, 4, 22 };

        SOME_DATA someData = new SOME_DATA();

        someData.x = Marshal.AllocHGlobal(x.Length * Marshal.SizeOf(typeof(double)));
        Marshal.Copy(x, 0, someData.x, x.Length);
        someData.y = Marshal.AllocHGlobal(y.Length * Marshal.SizeOf(typeof(double)));
        Marshal.Copy(y, 0, someData.y, y.Length);       
        someData.size = 50;
        someData.degree = 3;
        someData.df = 50;
        someData.order = 4;
        someData.lambda = 1;            

        return some_func(ref someData);
    }

I thought I was pretty dang close, but when I run this, the program just quits at the return statement.

Any ideas where I've gone wrong?

Thanks,

Mark

Upvotes: 1

Views: 2151

Answers (3)

arbiter
arbiter

Reputation: 9575

Seems like you forget to specify calling convention:

[DllImport("mydll.dll", EntryPoint="some_func", CallingConvention=CallingConvention.Cdecl)]

Upvotes: 1

Erich Mirabal
Erich Mirabal

Reputation: 10028

I would recommend a few things beyond what Ariel has suggested.

  1. Move the some_func(ref someData) statement to its own line before the return.
  2. Call Marshal.FreeHGlobal after that line (otherwise, it will be a memory leak).
  3. if order is equivalent to the array length, I would go ahead and use that.
  4. Do you have to specify the packing? Maybe your packing is off?

The only other idea I can suggest is to use double* in your struct and/or pin the arrays using the fixed statement.

Upvotes: 0

Ariel
Ariel

Reputation: 5830

Have you debugged into some_func? Try to windbg that program. Or use VS, but make sure to catch all exceptions and also enable mixed debugging.

Upvotes: 0

Related Questions