cmake 我得到以下PYBIND11_MODULE错误:“没有函数模板“pybind11::module_::def”的示例与参数列表匹配”

pgccezyw  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(126)

我克隆了这个:https://github.com/dickreuter/PokerEquityCalculator Github Repo并重写了它,以便它也适用于范围。整个代码似乎没有任何问题(因为VS Code没有高亮显示红色)。它唯一做的事情highlite red是下面的代码:

PYBIND11_MODULE(Scoring, m) {
    m.def("montecarlo", &montecarlo);
}

特别是.def()。我知道C++,这是我第一次使用pybind 11,所以我不知道它的意思。当用cmake编译代码时,它编译得很好,但它不会创建一个pyd或dll文件,我相信这是由这个错误引起的。
Scoring.cpp(错误为):

//cppimport

/*
<%
setup_pybind11(cfg)
%>
*/

#include "Scoring.h"

#include <array>
#include <vector>
#include <iostream>
#include <tuple>
#include <algorithm>

#include <iostream>
#include <algorithm>
#include <random>
#include <iterator>

#include <pybind11/pybind11.h>

#include <pybind11/stl.h>
#include <pybind11/complex.h>
#include <pybind11/functional.h>
#include <pybind11/chrono.h>

namespace py = pybind11;
using namespace pybind11::literals;

PYBIND11_MODULE(Scoring, m) {
    m.def("montecarlo", &montecarlo);
}

namespace
{
    constexpr auto x = std::array<int, 4>{2, 2, 2, 1};
}

bool eval_best_hand(const std::vector<std::set<std::string>>& all_cards_with_table_combined)
// returns true if first player has best hand
{
    std::vector<std::tuple< std::vector<int>, std::vector<int>, std::string>> all_players_score;
    std::vector<std::tuple< std::vector<int>, std::vector<int>, std::string>>  all_players_score_original;
    bool best_hand;

    for (const auto& cards_with_table : all_cards_with_table_combined)
    {
        auto result = calc_score(cards_with_table);
        all_players_score.emplace_back(result);
    }
    all_players_score_original = all_players_score;

    std::sort(all_players_score.begin(), all_players_score.end(), std::greater<>());
    if (all_players_score[0] == all_players_score_original[0])
        best_hand = true; // first player is best hand
    else
        best_hand = false; // different player is best hand

    return best_hand;
}

Score get_rcounts(const std::set<std::string>& all_cards_with_table_combined,
    std::vector<std::size_t> available_ranks,
    const std::string original_ranks) {
    Score rcounts;
    for (const auto& card : all_cards_with_table_combined) {
        available_ranks.emplace_back(original_ranks.find(card.substr(0, 1)));
    }
    for (int i = 0; i <= 12; i++) {
        int count = std::count(available_ranks.begin(), available_ranks.end(), i);
        if (count > 0) {
            rcounts.emplace_back(std::make_pair(count, i));
        }
    }
    return rcounts;
}

std::tuple< std::vector<int>, std::vector<int>, std::string> calc_score(const std::set<std::string>& all_cards_with_table_combined) {
    const std::string original_ranks = "23456789TJQKA";
    const std::vector<std::string> original_suits{ "C","D","H","S" };
    std::vector<std::size_t> available_ranks;
    std::vector<std::string> available_suits;
    std::vector<int> score;
    std::vector<int> card_ranks;
    std::vector<int> sorted_card_ranks;
    std::string hand_type;
    bool flush = false;
    bool straight = false;

    Score rcounts;
    std::vector<std::tuple<int, std::string>> rsuits;

    rcounts = get_rcounts(all_cards_with_table_combined, available_ranks, original_ranks);

    // sort tuple and split into score and card ranks
    std::sort(rcounts.begin(), rcounts.end(), std::greater<std::tuple<int, int>>());
    for (auto it = std::make_move_iterator(rcounts.begin()),
        end = std::make_move_iterator(rcounts.end()); it != end; ++it)
    {
        score.push_back(std::get<0>(*it));  // amount of occurrences
        card_ranks.push_back(std::get<1>(*it));  // ranks of individual cards
    }

    bool potential_threeofakind = score[0] == 3;
    bool potential_twopair = score == std::vector<int> {2, 2, 1, 1, 1};
    bool potential_pair = score == std::vector<int> {2, 1, 1, 1, 1, 1};

    auto sub_score2 = slice(score, 0, 2);
    auto sub_score4 = slice(score, 0, 5);
    auto sub_score0 = slice(score, 0, 0);
    // # fullhouse(three of a kind and pair, or two three of a kind)
    if (sub_score2 == std::vector<int> {3, 2} || sub_score2 == std::vector<int> {3, 3}) {
        // make adjustment
        card_ranks = slice(card_ranks, 0, 2);
        score = { 3,2 };
    }
    // edge case: convert three pair to two pair
    //const auto x = &score[3];
    else if (sub_score4 == std::vector<int>{2, 2, 2, 1}) {
        score = { 2,2,1 };
        int kicker = std::max(card_ranks[2], card_ranks[3]);
        card_ranks = { card_ranks[0], card_ranks[1], kicker };
    }
    else if (score[0] == 4) {  // four of a kind
        score = { 4, };
        // avoid for example 11, 8, 9
        sorted_card_ranks = card_ranks;
        std::sort(sorted_card_ranks.begin(), sorted_card_ranks.end(), std::greater <>());
        card_ranks = { sorted_card_ranks[0], sorted_card_ranks[1] };
    }
    else if (score.size() >= 5) {  // high card, flush, straight and straight flush
        // straight
        // adjust for 5 high straight
        if (std::find(card_ranks.begin(), card_ranks.end(), 12) != card_ranks.end())
            card_ranks.push_back(-1);
        sorted_card_ranks = card_ranks;
        std::sort(sorted_card_ranks.begin(), sorted_card_ranks.end(), std::greater <>());  // sort again

        for (int i = 0; i < sorted_card_ranks.size() - 4; ++i) {
            straight = sorted_card_ranks[i] - sorted_card_ranks[i + 4] == 4;
            if (straight == true) {
                card_ranks = {
                    sorted_card_ranks[i], sorted_card_ranks[i + 1], sorted_card_ranks[i + 2], sorted_card_ranks[i + 3],
                    sorted_card_ranks[i + 4] };
                break;
            }
        }

        //flush
        for (std::string card : all_cards_with_table_combined) {
            available_suits.emplace_back(card.substr(1, 1));
        }

        std::vector<int> suit_counts;
        std::vector<std::string> suit_cards;
        for (const auto& suit : original_suits) {  // why can original_suits not be a string and suit a char?
            int count = std::count(available_suits.begin(), available_suits.end(), suit);
            if (count > 0) {
                rsuits.emplace_back(std::make_pair(count, suit));
            }
        }
        std::sort(rsuits.begin(), rsuits.end(), std::greater<std::tuple<int, std::string>>());
        flush = std::get<0>(rsuits[0]) >= 5; // the most occurred suit appear at least 5 times

        if (flush == true)
        {
            auto flush_suit = std::get<1>(rsuits[0]);
            std::set<std::string> flush_hand;
            for (auto card : all_cards_with_table_combined) {
                if (card[1] == flush_suit[0]) {
                    flush_hand.insert(card);
                }
            }

            Score rcounts_flush = get_rcounts(flush_hand, available_ranks, original_ranks);
            // sort tuple and split into score and card ranks
            std::sort(rcounts_flush.begin(), rcounts_flush.end(), std::greater<std::tuple<int, int>>());
            card_ranks.clear();
            score.clear();
            for (auto it = std::make_move_iterator(rcounts_flush.begin()),
                end = std::make_move_iterator(rcounts_flush.end()); it != end; ++it)
            {
                score.push_back(std::get<0>(*it));  // ranks of individual cards
                card_ranks.push_back(std::get<1>(*it));  // amount of occurrences
            }

            //  # check for straight in flush
            // if 12 in card_ranks and -1 not in card_ranks : # adjust if 5 high straight
            if (std::find(card_ranks.begin(), card_ranks.end(), 12) != card_ranks.end() &&
                !(std::find(card_ranks.begin(), card_ranks.end(), -1) != card_ranks.end())) {
                card_ranks.push_back(-1);
            }

            for (int i = 0; i < card_ranks.size() - 4; i++) {
                straight = card_ranks[i] - card_ranks[i + 4] == 4;
                if (straight == true)
                {
                    break;
                }
            }
        }

        // no pair, straight, flush, or straight flush
        if (flush == false && straight == false)
            score = { 1 };
        else if (flush == false && straight == true)
            score = { 3, 1, 2 };
        else if (flush == true && straight == false)
            score = { 3, 1, 3 };
        else if (flush == true && straight == true)
            score = { 5 };
    }
    if (score[0] == 1 && potential_threeofakind == true)
        score = { 3,1 };
    else if (score[0] == 1 && potential_twopair == true)
        score = { 2, 2, 1 };
    else if (score[0] == 1 && potential_pair == true)
        score = { 2, 1, 1 };

    if (score[0] == 5)
        // # crdRanks=crdRanks[:5] # five card rule makes no difference {:5] would be incorrect
        hand_type = "StraightFlush";
    else if (score[0] == 4)
        hand_type = "FoufOfAKind"; // crdRanks = crdRanks[:2] # already implemented above
    else if (slice(score, 0, 2) == std::vector<int> {3, 2})
        hand_type = "FullHouse"; // # crdRanks = crdRanks[:2] # already implmeneted above
    else if (slice(score, 0, 3) == std::vector<int> {3, 1, 3}) {
        hand_type = "Flush";
        card_ranks = slice(card_ranks, 0, 5);
    }

    else if (slice(score, 0, 3) == std::vector<int> {3, 1, 2}) {
        hand_type = "Straight";
        card_ranks = slice(card_ranks, 0, 5);
    }

    else if (slice(score, 0, 2) == std::vector<int> {3, 1}) {
        hand_type = "ThreeOfAKind";
        card_ranks = slice(card_ranks, 0, 3);
    }
    else if (slice(score, 0, 2) == std::vector<int> {3, 1}) {
        hand_type = "ThreeOfAKind";
        card_ranks = slice(card_ranks, 0, 3);
    }
    else if (slice(score, 0, 2) == std::vector<int> {2, 2}) {
        hand_type = "TwoPair";
        card_ranks = slice(card_ranks, 0, 3);
    }
    else if (score[0] == 2) {
        hand_type = "Pair";
        card_ranks = slice(card_ranks, 0, 4);
    }
    else if (score[0] == 1) {
        hand_type = "HighCard";
        card_ranks = slice(card_ranks, 0, 5);
    }
    else
        throw std::runtime_error("Card Type error!");

    auto res = std::make_tuple(score, card_ranks, hand_type);
    return res;
}

double montecarlo(const std::set<std::string>& my_cards, const std::set<std::string>& cards_on_table, const std::vector<std::vector<std::set<std::string>>> ranges, const int number_of_players, const int iterations) { 

    int wins = 0;
    
    for (int i = 0; i < iterations; i++)
    {
        Deck deck;
        /*
        std::vector<int> idx_list;
        for (int i=0; i < ranges.size(); i++){
            idx_list.push_back(rand() % ranges[i].size());

        }      

        std::set<std::string> opponents_hole;
        for (auto i=0; i<ranges.size(); i++){
            for (auto it = ranges[i].begin(); it!=ranges[i].end(); it++){
        
            //auto it = next(ranges[i].begin(), idx_list[i]);   this was a mistake as this just gives us the card of the set and not the entire set
            //auto card_string = *it;
           //     opponents_hole.push_back(card_string);
            

            std::string choosen_opponent_pair = ranges[i][idx_list[i]];
            opponents_hole.insert(std::string(1, choosen_opponent_pair));
            } 
        }
    */       

     std::vector<int> idx_list;
     for (int i=0; i < ranges.size(); i++){
        std::random_device random_device;
        std::mt19937 engine{random_device()};
        std::uniform_int_distribution<int> dist(0, ranges[i].size() - 1);
        int k = dist(engine);
        idx_list.push_back(k);
      }
 
 /*
 22     std::set<std::string> opponents_hole;
 23     for (auto it = ranges[0][0].begin(); it != ranges[0][0].end(); ++it){
 24         std::string k = *it;
 25         std::cout << k;
 26         //std::string choosen_opponent_pair = ranges[i][idx_list[i]];
 27         //opponents_hole.insert(std::string(1, choosen_opponent_pair));
 28     }
 29     */

     std::vector<std::set<std::string>> opponents_hole;
     std::set<std::string> cards;
     for (int i=0; i<ranges.size(); i++){
         for (auto it = ranges[i][idx_list[i]].begin(); it!=ranges[i][idx_list[i]].end(); it++){
             //std::string choosen_opponent_pair = ranges[i][idx_list[i]];
            //opponents_hole.insert(std::string(1, choosen_opponent_pair));
             std::string k = *it;
             std::cout << k;
             cards.insert(k);
             if(cards.size()==2){
                 opponents_hole.push_back(cards);
                 cards.clear();
             }
             //opponents_hole.insert(cards);

         }

     }
        
        deck.remove_visible_cards(my_cards, cards_on_table);
        deck.distribute_cards(number_of_players, opponents_hole);
        std::vector<std::set<std::string>> cards_with_table_combined = deck.get_cards_combined();
        bool first_player_has_best_hand = eval_best_hand(cards_with_table_combined);
        if (first_player_has_best_hand == true)
            wins += 1;
    }
    double equity = (wins / (double)iterations) * 100.0;
    std::cout << "Equity: " << equity << "%" << std::endl;
    return equity;
}


Deck::Deck() {
    std::string combined;
    //std::cout << "Constructing deck..." << std::endl;
    for (char& r : ranks) {
        for (char& s : suits) {
            combined = std::string() + r + s;
            full_deck.insert(combined);
        };
    };
    //std::cout << "Cards in deck: " << full_deck.size() << std::endl;
}

void Deck::remove_visible_cards(const Hand& my_cards_, const std::set<std::string>& cards_on_table_) {
    // remove my_cards and cards_on_table from full_deck
    set_difference(full_deck.begin(), full_deck.end(), my_cards_.begin(), my_cards_.end(),
        std::inserter(remaining_cards_tmp, remaining_cards_tmp.end()));

    // remove visible table cards from deck
    set_difference(remaining_cards_tmp.begin(), remaining_cards_tmp.end(), cards_on_table_.begin(),
        cards_on_table_.end(),
        std::inserter(remaining_cards, remaining_cards.end()));

    //std::cout << "Remaining cards: " << remaining_cards.size() << std::endl;

    this->my_cards = my_cards_.cards;
    this->cards_on_table = cards_on_table_;

    //std::cout << "Removed my cards from deck...\n";
}

void Deck::distribute_cards(int number_players, const std::vector<std::set<std::string>>& opponents_hole) {  //number_players INLCUDING OURSELF
    constexpr size_t cards_in_hand = 2;

    std::vector<std::string> shuffled_deck(remaining_cards.begin(), remaining_cards.end());
    std::shuffle(shuffled_deck.begin(), shuffled_deck.end(), std::mt19937_64(std::random_device()()));
    std::vector<Hand> player_hands(number_players);  // empty container

    auto hand_it = player_hands.begin();
    *hand_it = Hand(my_cards);  // set my own cards
    hand_it++;

    auto card_it = shuffled_deck.begin();
    int i = 0;
    while (hand_it != player_hands.end() && i<opponents_hole.size()) {
        //*hand_it = Hand(std::set<std::string>{*++card_it, * ++card_it});
        //auto it = next(opponents_hole.begin(), i);
        //std::set<std::string>::iterator it = opponents_hole.begin();
        //std::advance(it, i);
        //*hand_it = Hand(*it);
        //++hand_it;
        //i++;
        *hand_it = Hand(opponents_hole[i]);
        i++;
    }

    i=0;

    while (cards_on_table.size() < 5) {
        cards_on_table.emplace(*++card_it);
    }

    // print out the hands
    //for (auto const& player_hand : player_hands) {
    //  std::cout << "Cards: ";
    //  for (const auto& card : player_hand.cards)
    //      std::cout << card << " ";
    //  std::cout << std::endl;
    //}
    this->player_hands = player_hands;

    //std::cout << "Cards on table: ";
    //print_set(cards_on_table);
}

std::vector<std::set<std::string>> Deck::get_cards_combined() {
    std::set<std::string> cards_with_table_combined;
    std::vector<std::set<std::string>> all_cards_with_table_combined;

    for (const auto& player_hand : player_hands) {
        cards_with_table_combined = player_hand.cards;
        cards_with_table_combined.insert(cards_on_table.begin(), cards_on_table.end());
        all_cards_with_table_combined.push_back(cards_with_table_combined);
    }

    return all_cards_with_table_combined;
}

void Deck::print_set(const std::set<std::string>& set) {
    for (const auto& card : set)
        std::cout << card << " ";
    std::cout << std::endl;
}

CMakeLists.txt

cmake_minimum_required (VERSION 3.27.1)

project (equity_calculator)
enable_language(C)
enable_language(CXX)

set(pybind11_DIR C:/Python39/Lib/site-packages/pybind11/share/cmake/pybind11)
set(PYTHON_EXECUTABLE C:/Python39/python.exe)
set(pybind11_LIBRARIES C:/Python39/libs/python39.lib)
find_package(pybind11 CONFIG REQUIRED)
include_directories(${pybind11_INCLUDE_DIRS})
message([MAIN] "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}")

MESSAGE( [Main] " pybind11_INCLUDE_DIRS = ${pybind11_INCLUDE_DIRS}")
MESSAGE( [Main] " pybind11_LIBRARIES = ${pybind11_LIBRARIES}")

#
#   # Create an extension module
#   add_library(mylib MODULE main.cpp)
#   target_link_libraries(mylib pybind11::module)
#
#   # Or embed the Python interpreter into an executable
#   add_executable(myexe main.cpp)
#   target_link_libraries(myexe pybind11::embed)

# method (1): generate `examplelib.pyd`
pybind11_add_module(Scoring Scoring.cpp)

# method (2): generate `examplelib.dll` rename to `examplelib.pyd`
#add_library(Scoring MODULE Scoring.cpp)
#target_link_libraries(Scoring pybind11::module)

MESSAGE( [Main] " pybind11_INCLUDE_DIRS = ${pybind11_INCLUDE_DIRS}")
MESSAGE( [Main] " pybind11_LIBRARIES = ${pybind11_LIBRARIES}")

#add_executable(cpp_use_python cpp_use_python.cpp)
#target_link_libraries(cpp_use_python PRIVATE pybind11::embed)

我试着把PYBIND11_MODULE放在最后,但它仍然不起作用。就像我说的,我从来没有使用过Pybind 11,所以我不知道这个错误意味着什么,也不知道为什么cmake不创建pyd文件。我还查看了官方的Pybind 11文档,特别是第一步页面,他们完全是这样做的,所以我不知道哪里出错了。
我会很感激任何帮助!提前感谢!

1szpjjfi

1szpjjfi1#

我现在已经解决了我的问题,改变了Scoring.h文件中以前没有看到的一行,现在我使用cppimport来使用蒙特卡洛函数,一切都很好。不过,当我使用cmake编译它时,它仍然不会创建pyd或dll文件。

相关问题