user3745869
user3745869

Reputation: 78

how to call a C .dll from C#?

I have tried to call the C struct from C#, but I failed to make it work. My struct define in C is as follow:

struct GHX{
    double output[28];
    int val;
};

And a function that I’m using to calculate the output is

__declspec(dllexport) void GHXfunction(
    double *XIN, double *parameter, 
    int mode, int hour, GHX *result)
{ 
    /*...*/
}

In C#, I tried the following method.

[StructLayout(LayoutKind.Sequential)]
public struct GHX
{
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 28)]
    public double[] output;
    public int val;
}
[DllImport("GHXDLL.dll", EntryPoint = "GHXfunction", 
    CallingConvention = CallingConvention.Cdecl)]
public static extern void GHXfunction(
    IntPtr XIN, IntPtr parameter, int mode, 
    int hour , ref GHX result);

So far, I believe that everything is OK, because someone from stackoverflow has the same problem as me. Then, I just test a simple scenario as follow.

static void Main()
{
    IntPtr XIN= IntPtr.Zero;
    IntPtr Par=IntPtr.Zero;
    int mode=1;
    int hour=0;
    GHX test = new GHX();
    GHXfunction(XIN, Par, mode, hour, ref test);
}

It then till me that "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Does anyone have idea about it? Thanks.

Edit, I actually don't know how does IntPtr work. So I guessed IntPtr.Zero will return memory location with 0, maybe i was wrong.

In my original C code I call the function like this

double par[42], xin[5];
ptrxin = &xin[0];
ptrpara = &par[0];
struct GHX result;
GHXfunction(ptrxin, ptrpara, 0, 0,result);

I dont know how to call the function in C# with the pointer input. Thanks.

Working code: Basing on Ben's suggestion. I can call the struct in C#.

   [StructLayout(LayoutKind.Sequential)]
    public struct GHX
    {
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 28)]
        public double[] output;
        public int val;
    }


    [DllImport("GHXDLL.dll", EntryPoint = "GHXfunction", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GHXfunction(double[] XIN, double[] parameter, int mode, int hour,ref GHX result);


    static void Main()
    {
        double result;
        double[] XIN= new double[5];
        double[] Par = new double[42];
        int mode = 1;
        int hour=0;
        GHX test = new GHX();
        GHXfunction(XIN, Par, mode, hour,ref test);
        result = test.output[0];

    }

Upvotes: 0

Views: 109

Answers (1)

Ben Voigt
Ben Voigt

Reputation: 283614

A C type of double* should be translated as either

ref double

or

double[]

Since your comments say those are arrays, try:

[DllImport("GHXDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void GHXfunction(double[] XIN, double[] parameter, int mode, 
                                      int hour , ref GHX result);

P/invoke will take care of pinning the array and passing the address of the first element.

Upvotes: 1

Related Questions