cjk84
cjk84

Reputation: 357

SafeArrayTypeMismatchException while trying to use unmanaged C++ DLL

First of all I'll say that I've searched high and low for the answer to this and when I have found something it's all gibberish to me, not being a C++ programmer. Programming is just a hobby for me.

I am using Visual Studio 2010 Ultimate, in a C# winforms project, in case that helps!

The problem is that I am trying to use a function from an unmanaged DLL (Bo Haglund's Double Dummy Solver). His readme is less than helpful and there are surprisingly few (ie, no) articles on how to use his DLL.

I have the prototype for the function in the DLL that I wish to use.

extern "C" __declspec(dllimport) int __stdcall CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep);

I don't really know much about pointers, but I guessed that I would use "ref" in C#.

Here is his readme on the function:

CalcDDtable

CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/declarer hand combinations.

Before CalcDDtable can be called, a structure of type " ddTableResults" must be declared. CalcDDtable returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure. Status codes:
1=No fault, Other status codes are errors, with codes equal to SolveBoard status codes.

Structure ”ddTableDeal” defines the dealt cards to be analyzed. struct ddTableDeal { unsigned int cards[4][4]; /* 1st index is hand, 2nd index is suit, same coding as for deal.remainCards for SolveBoard. */ };

struct ddTableResults { /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */
  int resTable[5][4];   /* 1st index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2nd index is declarer hand, 0=North, 1=East, 2=South, 3=West */
};

CalcDDtablePBN

In CalcDDtablePBN the remaining cards in the deal information are given in PBN text format, see the description above for SolveBoardPBN. Otherwise, CalcDDtablePBN is identical to CalcDDtable.

struct ddTableDealPBN {
  char cards[80];
};

I imported the function as follows:

[DllImport("dds.dll")]
public static extern int CalcDDtablePBN(DDTableDealPBNStruct tableDealPBN, ref DDTableResultsStruct tablep);

Here are my structs:

public struct DDTableDealPBNStruct
{
    public char[] cards;

    public DDTableDealPBNStruct(char[] pbnCards)
    {
        cards = pbnCards;
    }
}

public struct DDTableResultsStruct
{
    public short[,] resTable; /* 1st index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2nd index is declarer hand, 0=North, 1=East, 2=South, 3=West */
}

And this is how I call the function:

const string _dealPBN = "N:QJT..AJ76.AKJ765 AK64.AKJ7654..98 32.T932.KQ32.T43 9875.Q8.T9854.Q2";
DDTableDealPBNStruct tdPBN = new DDTableDealPBNStruct(_dealPBN.ToCharArray());
DDTableResultsStruct results = new DDTableResultsStruct();
results.resTable = new short[5, 4];
CalcDDtablePBN(tdPBN, ref results);

When I run the program, this is the error message I get:

SafeArrayTypeMismatchException was unhandled. Specified array was not of the expected type.

It does not mention which array was bad, but I would be guessing that it is the short[5,4] array. I tried different [MarshalAs(UnmanagedType.blah)] options to no avail. Can anyone tell me what I'm doing wrong? I am honestly stumped.

I have also tried a few different array types, int, uint, short, Int16, etc, again to no avail. Unless I'm wrong and it's the char[] array that it is complaining about?

Thank you in advance.

Upvotes: 0

Views: 1775

Answers (1)

ymett
ymett

Reputation: 2454

You need to describe the layout of the struct.

[StructLayout(LayoutKind.Sequential)]
public struct DDTableResultsStruct
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    public int[] resTable;
}

There doesn't seem to be a way to say the array is 2-dimensional, so I've just given the full size of the array as if it was 1-dimensional. (In C a multdimensional array is laid out contiguously in memory.) Note that the element type is int, not short -- it's 32 bit. You should do the same for the other struct as well.

(Untested code.)

Upvotes: 1

Related Questions