Как я могу вручную создать расширение C ++ с помощью mingw-w64, Python и pybind11?

Моя конечная цель - скомпилировать расширение Python C ++ из моего кода C ++. В настоящее время, чтобы начать работу, я следую простому примеру из первых шагов pybind11 документации. Моя рабочая среда - это 64-разрядная версия Windows 7 Professional, mingw-w64 (x86_64-8.1.0-posix-seh-rt_v6-rev0) и Anaconda3 с 64-разрядной версией Python 3.7.4. У меня 2 файла. Первый - это файл C ++ - example.cpp.

#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example plugin"; // optional module docstring

    m.def("add", &add, "A function which adds two numbers");
}

Я компилирую файл C ++ с помощью следующей команды:


C:/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/g++.exe -shared -std=c++11 -DMS_WIN64 -fPIC -ID:\Users\ADAS\anaconda3\Include -ID:\Users\ADAS\anaconda3\Library\include -ID:\Users\ADAS\anaconda3\pkgs\python-3.7.4-h5263a28_0\include -Wall -LD:\Users\ADAS\anaconda3\Lib -LD:\Users\ADAS\anaconda3\pkgs\python-3.7.4-h5263a28_0\libs example.cpp -o example.dll -lPython37

Результат компиляции успешен, и я получаю example.dll файл.

На следующем шаге я запускаю следующий код Python - example.py:

import example

def main():
    i, j = (1, 2)
    res = example.add(i, j)
    print("%d + %d = %d" % (i, j, res))

if __name__ == '__main__':
    main()

И здесь у меня проблема. Кажется, что строка import example не выдает никаких предупреждений или ошибок, но строка res = example.add(i, j) выдает ошибку:

AttributeError: module 'example' has no attribute 'add'

В Ubuntu 18.04 я успешно скомпилировал и запустил на Python приведенный выше пример, но в моем офисе у меня только Windows 7.

Вопросы: что не так в моей настройке или в командной строке? Можно ли решить эту проблему, не меняя текущий компилятор C ++ (mingw-w64 версии 8.1) под Windows?


person Vladimir S.    schedule 16.03.2020    source источник


Ответы (1)


Это невероятно! Проблема заключалась только в расширении скомпилированного файла. Как только я изменил .dll на .pyd, пример Python (example.py) работает без проблем!

Итак, новая командная строка:

C:/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/g++.exe -shared -std=c++11 -DMS_WIN64 -fPIC -ID:\Users\ADAS\anaconda3\Include -ID:\Users\ADAS\anaconda3\Library\include -ID:\Users\ADAS\anaconda3\pkgs\python-3.7.4-h5263a28_0\include -Wall -LD:\Users\ADAS\anaconda3\Lib -LD:\Users\ADAS\anaconda3\pkgs\python-3.7.4-h5263a28_0\libs example.cpp -o example.pyd -lPython37

Поскольку я провел несколько экспериментов с аргументами командной строки, я собираюсь еще раз проверить все аргументы компилятора, чтобы убедиться, что он дает успешный результат. Я дам вам знать, если еще потребуются какие-то изменения.

Обновление1:

Согласно настройкам Python3 по умолчанию, полное расширение скомпилированного файла C ++ под Windows должно быть .cp37-win_amd64.pyd.

Мы можем получить расширение с помощью команды терминала:

python -c "from distutils import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"

Это эквивалент python3-config --extension-suffix из документации pybind11. Скрипт python3-config не реализован в среде Windows (по крайней мере, в дистрибутиве Anaconda3).

person Vladimir S.    schedule 16.03.2020