Search code examples
c++pipcmath

using cmath special functions extending Python with C++


I am trying to build a Python package in C++, and when I build, I get no errors; however, when I use pip install, I get the following result:

----- Installing 'D:\GitHub\dir\dir\ --user' -----
Processing d:\github\dir\dir
  Installing build dependencies: started
  Installing build dependencies: finished with status 'done'
  Getting requirements to build wheel: started
  Getting requirements to build wheel: finished with status 'done'
  Preparing metadata (pyproject.toml): started
  Preparing metadata (pyproject.toml): finished with status 'done'
Building wheels for collected packages: package_name
  Building wheel for package_name (pyproject.toml): started
  Building wheel for package_name (pyproject.toml): finished with status 'error'
  error: subprocess-exited-with-error
  
  Building wheel for package_name (pyproject.toml) did not run successfully.
  exit code: 1
  
  [14 lines of output]
Failed to build package_name
  running bdist_wheel
  running build
  running build_ext
  building 'package_name' extension
  "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\bin\HostX86\x64\cl.exe" /c /nologo /O2 /W3 /GL /DNDEBUG /MD -IC:\Users\etcto\AppData\Local\Programs\Python\Python310\include -IC:\Users\etcto\AppData\Local\Programs\Python\Python310\Include "-IC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include" "-IC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\ATLMFC\include" "-IC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\um" "-IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\shared" "-IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\winrt" "-IC:\Program Files (x86)\Windows Kits\10\\include\10.0.19041.0\\cppwinrt" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" /EHsc /Tpmodule.cpp /Fobuild\temp.win-amd64-cpython-310\Release\module.obj
  module.cpp
  module.cpp(28): error C2039: 'comp_ellint_1f': is not a member of 'std'
  C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\cmath(710): note: see declaration of 'std'
  module.cpp(28): error C3861: 'comp_ellint_1f': identifier not found
  module.cpp(28): error C2039: 'comp_ellint_1f': is not a member of 'std'
  C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.33.31629\include\cmath(710): note: see declaration of 'std'
  module.cpp(28): error C3861: 'comp_ellint_1f': identifier not found
  module.cpp(61): warning C4244: 'argument': conversion from 'double' to 'float', possible loss of data
  error: command 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.33.31629\\bin\\HostX86\\x64\\cl.exe' failed with exit code 2
  [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for package_name
ERROR: Could not build wheels for package_name, which is required to install pyproject.toml-based projects
----- Failed to install 'D:\GitHub\dir\dir\ --user' -----

I have a feeling it's trying to use C++ 14 (which didn't include comp_ellint_1f) because I see the number in the directories listed, but in my properties page (for both Release and Debug), I have the "C++ Language Standard" set to "ISO C++ 20 Standard (/std:c++20)".

When I remove that function from the project, pip installs the package just fine, and I can import it into Python without issue. I am not sure how to tell it to use C++ 20 for the pip install portion.

MRE:

#include <Python.h>
#include <Windows.h>
#include <cmath>
PyObject* k_func(PyObject* /* unused module reference */, PyObject* args) {
    double k, integral;

    PyArg_ParseTuple(args, "d", &k);

    double integral = std::comp_ellint_1(k);
    return PyFloat_FromDouble(integral);
}
static PyMethodDef package_name_methods[] = {
    // The first property is the name exposed to Python, k
    // The second is the C++ function with the implementation
    // METH_O means it takes a single PyObject argument
    { "ellipticK", (PyCFunction)k_func, METH_VARARGS, "Calculate elliptic integral" },

    // Terminate the array with an object containing nulls.
    { nullptr, nullptr, 0, nullptr }
};

static PyModuleDef package_name_module = {
    PyModuleDef_HEAD_INIT,
    "package_name",
    "Module Description",
    0,
    package_name_methods
};

PyMODINIT_FUNC PyInit_package_name() {
    return PyModule_Create(&package_name_module);
}

pyproject.toml is

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

setup.py is

from setuptools import setup, Extension

sfc_module = Extension('package_name', sources = ['module.cpp'])

setup(
    name='package_name',
    version='0.0',
    description='Description',
    ext_modules=[sfc_module]
)

Solution

  • Thanks for the compiler flag suggestion; the following worked:

    from setuptools import setup, Extension
    
    sfc_module = Extension('package_name', sources = ['module.cpp'],
                           extra_compile_args=["/std:c++20"],
                           )
    
    setup(
        name='package_name',
        version='0.0',
        scripts=[],
        ext_modules=[sfc_module]
    )