lundi 20 juin 2016

C# calling C++ 3rd party DLL (no source) raises exception - not PInvoke Compatible

I am using VS 2015 Community with an ASP.NET MVC Web Application that uses a 3rd party C++ DLL I do not have source code for. Documentation is very scarce as is any helpful communication with the authors of the 3rd party DLL.

I've asked a related SO Question and received a good answer from @Steven. I've modified my code according to his answer and am trying to make a successful call to the 3rd party C++ DLL. The code:

// Call DLL

MyDLLInput _DLLInput = new MyDLLInput();
{
    SomeList = new int[288],
    ...
    SomeInt = 22,
    SomeDbl = 1.45,
    ...
    PathtoData = "C:\Some\Path\To\Data"
};    

var ids = new int[] { 0, 12, 33, 67, 93 };
Array.Copy(ids, _DLLInput.SomeList, ids.Length);

// Call DLL Entry Point
MyDLLOutput _DLLOutput = MyDLL.Unit(_DLLInput);

Raises exception:

Method's type signature is not PInvoke compatible.

// C# Input STRUCT

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyDLLInput
{
    public const int DI_NUMOFMODELS = 288;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = DI_NUMOFMODELS)]
    public int[] SomeList;
    ...
    public int SomeInt;
    public double SomeDbl;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string PathtoData;
};

// C# Output STRUCT

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyDLLOutput
{
    public const int DI_NUMOFMODELS = 288;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = DI_NUMOFMODELS)]
    public int[] SomeList;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = DI_NUMOFMODELS)]
    public double[] SomeDblArray;
    ...
    public int SomeInt;        // Same as input
    public double SomeDbl;     // Same as input
}

// C# DLLImport

public class MyDLL
{
    [DllImport("My_DLL.dll",
        EntryPoint = "?Unit@@YA?AUDLLOutput@@UDLLInput@@@Z",
        CallingConvention = CallingConvention.Cdecl)]
    public static extern MyDLLOutput Unit(MyDLLInput UnitInput);
}

// C++ My_DLL.h

#define  EPS_API __declspec(dllexport) 

struct DLLInput
{
    int SomeList[288];

    int SomeInt;
    double SomeDbl;

    char PathtoData[256];
};

struct DLLOutput
{
    int SomeList[288];
    double SomeDblArray[288];
    ...
    int SomeInt;
    double SomeDbl;
};

EPS_API DLLOutput Unit(DLLInput UnitInput);

I think I must be close, but haven't been able to find any SO or Google results that help. Does anyone see what I'm doing wrong?

Aucun commentaire:

Enregistrer un commentaire