Pybind11: Can't bind a cpp function named `read`

Created on 6 Aug 2019  路  5Comments  路  Source: pybind/pybind11

Issue description

If you try to bind a cpp function called read you get

error: no matching function for call to 'pybind11::module::def(const char [5], <unresolved overloaded function type>, const char [14])'

Reproducible example code

// bind.cpp

#include <pybind11/pybind11.h>
namespace py = pybind11;

int read() {}

PYBIND11_MODULE(bind, m) {
    m.def("read", &read, "reading stuff");
}

compiling with

g++ -O3 -std=c++1z -fPIC -shared `python3 -m pybind11 --includes` -o bind.so bind.cpp

Some thoughts

It appears read function is already defined, so pybind11 sees it as an overload of that other function and starts freaking out.

If I compile a file which has just one line

int r = read;

I get error: 'read' was not declared in this scope, but if I compile

#include <pybind11/pybind11.h>
int r = read;

I get error: invalid conversion from 'ssize_t (*)(int, void*, size_t) {aka long int (*)(int, void*, long unsigned int)}' to 'int' [-fpermissive].

I think it is a problem with one of dependencies of pybind11 that exposes a function called read but I can't tell where does it come from.

All 5 comments

The issue here is with overload resolution, covered here in the docs.

For your case, if you are able to use C++14, this works:

#include <pybind11/pybind11.h>
namespace py = pybind11;

int read() {
return 1;
}
PYBIND11_MODULE(bind, m) {
    m.def("read", py::overload_cast<>(&::read), "reading stuff");
}

Alternately, wrap your own code in a namespace and be explicit about that when writing the wrappers.

@molpopgen Thanks for specifying ways to work around this. I am however concerned about the very fact that you have a function (with a fairy common name) in the global namespace, which ideally should not happen.

Well, I don't have such a function--I'm not one of the devs. However, the function doesn't come from pybind11:

find include/|xargs grep "read(" 
grep: include/: Is a directory
grep: include/pybind11: Is a directory
grep: include/pybind11/detail: Is a directory
include/pybind11/pybind11.h:            PyEval_AcquireThread(tstate);
include/pybind11/pybind11.h:           PyEval_SaveThread();
include/pybind11/pybind11.h:        tstate = PyEval_SaveThread();
include/pybind11/pybind11.h:        PyEval_RestoreThread(tstate);
include/pybind11/pybind11.h:    gil_scoped_release() { state = PyEval_SaveThread(); }
include/pybind11/pybind11.h:    ~gil_scoped_release() { PyEval_RestoreThread(state); }

ssize_t read(int fildes, void *buf, size_t nbyte);

https://linux.die.net/man/3/read

Right. This is either the POSIX read() or whatever. static_cast<void(*)()>(read) works as well.

Was this page helpful?
0 / 5 - 0 ratings