3F / DllExport

.NET DllExport with .NET Core support (aka 3F/DllExport aka DllExport.bat)
MIT License
940 stars 131 forks source link

Error CS0103 The name 'CallingConvention' does not exist in the current context #92

Closed hughfuve closed 5 years ago

hughfuve commented 5 years ago

How to reproduce

Trying to build this DLL and expose the functions outside of C# https://www.codeproject.com/KB/game/pokerhandevaldoc/PokerHandEvalSrc.zip

install unmanagedExports through VS nuget package manager Then add name space...

using RGiesecke.DllExport;

then add the following to method definition within the class... DllExport("add", CallingConvention = CallingConvention.Cdecl)]

try to build... and then we get error... Error CS0103 The name 'CallingConvention' does not exist in the current context

Version, configuration, commands:

unmanagedExports V1.2.7 Microsoft Visual Studio Community 2017 Version 15.9.6 VisualStudio.15.Release/15.9.6+28307.344 Microsoft .NET Framework Version 4.7.03056 Installed Version: Community

NuGet Package Manager 4.6.0

Project files, samples:

using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using RGiesecke.DllExport;

namespace HoldemHand { public partial class Hand : IComparable {

region Analysis Functions

    /// <summary>
    /// Used to calculate the wining information about each players hand. This function enumerates all 
    /// possible remaining hands and tallies win, tie and losses for each player. This function typically takes
    /// well less than a second regardless of the number of players.
    /// </summary>
    /// <param name="pockets">Array of pocket hand string, one for each player</param>
    /// <param name="board">the board cards</param>
    /// <param name="dead">the dead cards</param>
    /// <param name="wins">An array of win tallies, one for each player</param>
    /// <param name="ties">An array of tie tallies, one for each player</param>
    /// <param name="losses">An array of losses tallies, one for each player</param>
    /// <param name="totalHands">The total number of hands enumarated.</param>

   [DllExport("add", CallingConvention = CallingConvention.Cdecl)]
    public static void HandOdds(string[] pockets, string board, string dead, long[] wins, long[] ties, long[] losses, ref long totalHands)
    {
        ulong[] pocketmasks = new ulong[pockets.Length];
        ulong[] pockethands = new ulong[pockets.Length];
        int count = 0, bestcount;
        ulong boardmask = 0UL, deadcards_mask = 0UL, deadcards = Hand.ParseHand(dead, ref count);

        totalHands = 0;
        deadcards_mask |= deadcards;

        // Read pocket cards
        for (int i = 0; i < pockets.Length; i++)
        {
            count = 0;
            pocketmasks[i] = Hand.ParseHand(pockets[i], "", ref count);
            if (count != 2)
                throw new ArgumentException("There must be two pocket cards."); // Must have 2 cards in each pocket card set.
            deadcards_mask |= pocketmasks[i];
            wins[i] = ties[i] = losses[i] = 0;
        }

        // Read board cards
        count = 0;
        boardmask = Hand.ParseHand("", board, ref count);

if DEBUG

        Debug.Assert(count >= 0 && count <= 5); // The board must have zero or more cards but no more than a total of 5

        // Check pocket cards, board, and dead cards for duplicates
        if ((boardmask & deadcards) != 0)
            throw new ArgumentException("Duplicate between cards dead cards and board");

        // Validate the input
        for (int i = 0; i < pockets.Length; i++)
        {
            for (int j = i + 1; j < pockets.Length; j++)
            {
                if ((pocketmasks[i] & pocketmasks[j]) != 0)
                    throw new ArgumentException("Duplicate pocket cards");
            }

            if ((pocketmasks[i] & boardmask) != 0)
                throw new ArgumentException("Duplicate between cards pocket and board");

            if ((pocketmasks[i] & deadcards) != 0)
                throw new ArgumentException("Duplicate between cards pocket and dead cards");
        }

endif

        // Iterate through all board possiblities that doesn't include any pocket cards.
        foreach (ulong boardhand in Hands(boardmask, deadcards_mask, 5))
        {
            // Evaluate all hands and determine the best hand
            ulong bestpocket = Evaluate(pocketmasks[0] | boardhand, 7);
            pockethands[0] = bestpocket;
            bestcount = 1;
            for (int i = 1; i < pockets.Length; i++)
            {
                pockethands[i] = Evaluate(pocketmasks[i] | boardhand, 7);
                if (pockethands[i] > bestpocket)
                {
                    bestpocket = pockethands[i];
                    bestcount = 1;
                }
                else if (pockethands[i] == bestpocket)
                {
                    bestcount++;
                }
            }

            // Calculate wins/ties/loses for each pocket + board combination.
            for (int i = 0; i < pockets.Length; i++)
            {
                if (pockethands[i] == bestpocket)
                {
                    if (bestcount > 1)
                    {
                        ties[i]++;
                    }
                    else
                    {
                        wins[i]++;
                    }
                }
                else if (pockethands[i] < bestpocket)
                {
                    losses[i]++;
                }
            }

            totalHands++;
        }
    }

... more methods follow...

log

hughfuve commented 5 years ago

my guess is that this is something to do with this line...

public partial class Hand : IComparable

The code is trying to use Interfaces, and this is breaking the build, because they're incompatible.

My guess is that the solution will be to build some kind of wrapper inside the code which exposes the methods of the function using the expected CDECL format.

I'm also guessing this is not the place to ask such questions, but I really don't know where else we would ask, and I'm sure I;m not the only one who sees this kind of error, anyone looking for a fix will find this post.

3F commented 5 years ago

@hughfuve

unmanagedExports V1.2.7

Your package does not related to this project. Look here: https://www.nuget.org/packages/DllExport/

Please read this: https://github.com/3F/DllExport/wiki/Quick-start

Error CS0103 The name 'CallingConvention' does not exist in the current context

You just need to use System.Runtime.InteropServices namespace.

using the expected CDECL format.

Our tool uses Cdecl by default. You don't need to do anything else for your case.