Reputation: 357
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
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