pybind / pybind/pybind11

Implicit conversion of pointer-type arguments

Open
#1,409 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C++
Stars
18k
Forks
2.3k
Avg merge
5d 17h
Merged PRs (30d)
10

Description

Issue description

The current implicit conversion system doesn't allow to specify conversion for pointer type arguments, even though the same call would work in c++ (see the code).

The main problem seems to be that pybind11's function type detection always assumes the base type (i.e. A) to be the exposed one. If there were a possibility to declare a py::class_<A*>(m, "APtr") and force the function to accept it instead of A (by specifying an attribute on py::arg for example) it would solve the problem without making the more common use case any more cumbersome.

EDIT: you could solve this problem by defining a copyable wrapper class around A and Container_of_A convertible to it.

Reproducible example code

#include <pybind11/pybind11.h>
#include <iostream>

using namespace std;
namespace py = pybind11;

struct A {
  A(const A& a) = delete;
  explicit A(int value) : value(value) { };
  int value;
};

struct Container_of_A {
  A* a;
  // define conversion
  operator A* () { return this->a; }
};

int test1(A* a) {
  return a->value;
}

PYBIND11_MODULE(conversion, m) {
  // sanity check
  A a(10);
  Container_of_A cont = {&a};
  cout << "Test 2: " << test1(cont) << endl;
  py::class_<A>(m, "A")
    .def(py::init<int>());
  //.def(py::init<Container_of_A>) doesn't work, since you can't initalize an instance of A with a pointer
  py::class_<Container_of_A>(m, "Container_of_A")
    .def(py::init<A*>());
  py::implicitly_convertible<Container_of_A, A>();
  m.def("test1", &test1, py::return_value_policy::reference);
}
#!/usr/bin/env python3
import conversion as conv

a = conv.A(10)
container = conv.Container_of_A(a)
print('Success 1: ', conv.test1(a))
print('Failure 1: ', conv.test1(container))

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The named entry points are py::implicitly_convertible, py::arg, py::class_, and the bound test1(A*) function; start by tracing function type detection for pointer arguments. Use the supplied C++ and Python reproducer as regression coverage. Done means conv.test1(container) succeeds while conv.test1(a) continues to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.