Skip to content

Can't bind functions taking char& as an argument #1116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lyskov opened this issue Sep 27, 2017 · 11 comments
Closed

Can't bind functions taking char& as an argument #1116

lyskov opened this issue Sep 27, 2017 · 11 comments

Comments

@lyskov
Copy link
Contributor

lyskov commented Sep 27, 2017

Dear Pybind11 developers,
Looks like both latest master and stable seems to produce an error when trying to bind function taking char &. Could you please looks this up?

Thanks,

#include <pybind11/pybind11.h>

void foo_char(char &) {}
void foo_bool(bool &) {}
void foo_int(int &) {}
void foo_long(long &) {}
void foo_long_long(long long &) {}
void foo_float(float &) {}
void foo_double(double &) {}

PYBIND11_PLUGIN(example) {
    pybind11::module m("example", "pybind11 example plugin");

	m.def("foo_char",      &foo_char);
	m.def("foo_bool",      &foo_bool);
	m.def("foo_int",       &foo_int);
	m.def("foo_long",      &foo_long);
	m.def("foo_long_long", &foo_long_long);
	m.def("foo_float",     &foo_float);
	m.def("foo_double",    &foo_double);

    return m.ptr();
}

Error:

In file included from /home/benchmark/src/pybind11/include/pybind11/pybind11.h:43:
In file included from /home/benchmark/src/pybind11/include/pybind11/attr.h:13:
/home/benchmark/src/pybind11/include/pybind11/cast.h:1858:38: error: non-const lvalue reference to type 'char' cannot bind to a temporary of type 'typename make_caster<char &>::cast_op_type<typename std::add_rvalue_reference<char &>::type>' (aka 'char')
        return std::forward<Func>(f)(cast_op<Args>(std::move(std::get<Is>(argcasters)))...);
                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/benchmark/src/pybind11/include/pybind11/cast.h:1840:35: note: in instantiation of function template specialization 'pybind11::detail::argument_loader<char &>::call_impl<void, void (*&)(char &), 0, pybind11::detail::void_type>' requested here
        std::move(*this).template call_impl<Return>(std::forward<Func>(f), indices{}, Guard{});
                                  ^
/home/benchmark/src/pybind11/include/pybind11/pybind11.h:154:52: note: in instantiation of function template specialization 'pybind11::detail::argument_loader<char &>::call<void, pybind11::detail::void_type, void (*&)(char &)>' requested here
                std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent);
                                                   ^
/home/benchmark/src/pybind11/include/pybind11/pybind11.h:58:9: note: in instantiation of function template specialization 'pybind11::cpp_function::initialize<void (*&)(char &), void, char &, pybind11::name, pybind11::scope, pybind11::sibling>' requested here
        initialize(f, f, extra...);
        ^
/home/benchmark/src/pybind11/include/pybind11/pybind11.h:806:22: note: in instantiation of function template specialization 'pybind11::cpp_function::cpp_function<void, char &, pybind11::name, pybind11::scope, pybind11::sibling>' requested here
        cpp_function func(std::forward<Func>(f), name(name_), scope(*this),
                     ^
ret-reference.cpp:14:4: note: in instantiation of function template specialization 'pybind11::module::def<void (*)(char &)>' requested here
        m.def("foo_char",      &foo_char);
          ^
1 warning and 1 error generated.
@jagerman
Copy link
Member

I'm away for a couple days and won't be able to look into this in detail until I get back, but one quick question: did it work in 2.1?

@lyskov
Copy link
Contributor Author

lyskov commented Sep 28, 2017

It certainly worked before i merged last Pybind11 upstream... but it am not sure if it was after 2.1 or before it. However i can tell you exact commit where it was still working: it is Dec 16, 2016 RosettaCommons@1d1f81b

Thank you!

@lyskov
Copy link
Contributor Author

lyskov commented Oct 2, 2017

Small update: it looks like returning char & is still ok, - no compilation errors. Hope this helps!

@lyskov
Copy link
Contributor Author

lyskov commented Oct 6, 2017

@jagerman are there any unexpected complication with this? Should i plan to implement work around for this for now?

jagerman added a commit to jagerman/pybind11 that referenced this issue Oct 6, 2017
This changes the caster to return a reference to a (new) local `CharT`
type caster member so that binding lvalue-reference char arguments
works (currently it results in a compilation failure).

Fixes pybind#1116
@jagerman
Copy link
Member

jagerman commented Oct 6, 2017

See #1128; that should fix it.

@lyskov
Copy link
Contributor Author

lyskov commented Oct 6, 2017

Great, thank you @jagerman !

@lyskov
Copy link
Contributor Author

lyskov commented Oct 6, 2017

Just letting you know that i tested this and it works fine, - thanks again!

@trelau
Copy link
Contributor

trelau commented Oct 9, 2017

In case this is related, in a C++ library I am trying to wrap I get a compilation error with some character inputs. This reproduces the error on MSVC with both the pybind11 master and the branch for this fix:

#include <pybind11\pybind11.h>

namespace py = pybind11;

typedef const char* TheString;

void TheMethod(TheString& theString) {};

PYBIND11_MODULE(pymod2, mod) {

	mod.def("TheMethod", (void (*) (TheString &)) &TheMethod);
	
}

results in

'void (TheString &)': cannot convert argument 1 from 'char *' to 'TheString &'

jagerman added a commit that referenced this issue Oct 12, 2017
This changes the caster to return a reference to a (new) local `CharT`
type caster member so that binding lvalue-reference char arguments
works (currently it results in a compilation failure).

Fixes #1116
@jagerman
Copy link
Member

@trelau - I've just merged #1128; what you have there looks like a different issue (though in a related part of the code); can you file a new issue for it?

@trelau
Copy link
Contributor

trelau commented Oct 12, 2017

@jagerman Done. Thanks for the support.

jagerman added a commit to jagerman/pybind11 that referenced this issue Jan 12, 2018
This changes the caster to return a reference to a (new) local `CharT`
type caster member so that binding lvalue-reference char arguments
works (currently it results in a compilation failure).

Fixes pybind#1116
wjakob pushed a commit that referenced this issue Feb 7, 2018
This changes the caster to return a reference to a (new) local `CharT`
type caster member so that binding lvalue-reference char arguments
works (currently it results in a compilation failure).

Fixes #1116
@bbrighttaer
Copy link

bbrighttaer commented Dec 29, 2018

Hello @jagerman,
I am also facing a similar issue with a wrapper I am creating for my work:

/home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h: In instantiation of ‘Return pybind11::detail::argument_loader<Args>::call_impl(Func&&, pybind11::detail::index_sequence<Is ...>, Guard&&) [with Return = int; Func = int (*&)(char**, int*); long unsigned int ...Is = {0, 1}; Guard = pybind11::detail::void_type; Args = {char**, int*}]’: /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h:1851:101: required from ‘pybind11::detail::enable_if_t<(! std::is_void<_Yp>::value), Return> pybind11::detail::argument_loader<Args>::call(Func&&) && [with Return = int; Guard = pybind11::detail::void_type; Func = int (*&)(char**, int*); Args = {char**, int*}; pybind11::detail::enable_if_t<(! std::is_void<_Yp>::value), Return> = int]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:154:43: required from ‘pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...)::<lambda(pybind11::detail::function_call&)> [with Func = int (*&)(char**, int*); Return = int; Args = {char**, int*}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [33]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:132:22: required from ‘struct pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = int (*&)(char**, int*); Return = int; Args = {char**, int*}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [33]}]::<lambda(struct pybind11::detail::function_call&)>’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:132:19: required from ‘void pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = int (*&)(char**, int*); Return = int; Args = {char**, int*}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [33]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:58:9: required from ‘pybind11::cpp_function::cpp_function(Return (*)(Args ...), const Extra& ...) [with Return = int; Args = {char**, int*}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [33]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:813:22: required from ‘pybind11::module& pybind11::module::def(const char*, Func&&, const Extra& ...) [with Func = int (*)(char**, int*); Extra = {char [33]}]’ imagopy/cbinding/imagopy.cpp:90:45: required from here /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h:1874:37: error: cannot convert ‘pybind11::detail::type_caster<char, void>::cast_op_type<char**&&> {aka char*}’ to ‘char**’ in argument passing return std::forward<Func>(f)(cast_op<Args>(std::move(std::get<Is>(argcasters)))...); ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h: In instantiation of ‘Return pybind11::detail::argument_loader<Args>::call_impl(Func&&, pybind11::detail::index_sequence<Is ...>, Guard&&) [with Return = int; Func = int (*&)(unsigned char**, int*, int*); long unsigned int ...Is = {0, 1, 2}; Guard = pybind11::detail::void_type; Args = {unsigned char**, int*, int*}]’: /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h:1851:101: required from ‘pybind11::detail::enable_if_t<(! std::is_void<_Yp>::value), Return> pybind11::detail::argument_loader<Args>::call(Func&&) && [with Return = int; Guard = pybind11::detail::void_type; Func = int (*&)(unsigned char**, int*, int*); Args = {unsigned char**, int*, int*}; pybind11::detail::enable_if_t<(! std::is_void<_Yp>::value), Return> = int]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:154:43: required from ‘pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...)::<lambda(pybind11::detail::function_call&)> [with Func = int (*&)(unsigned char**, int*, int*); Return = int; Args = {unsigned char**, int*, int*}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [28]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:132:22: required from ‘struct pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = int (*&)(unsigned char**, int*, int*); Return = int; Args = {unsigned char**, int*, int*}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [28]}]::<lambda(struct pybind11::detail::function_call&)>’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:132:19: required from ‘void pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = int (*&)(unsigned char**, int*, int*); Return = int; Args = {unsigned char**, int*, int*}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [28]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:58:9: required from ‘pybind11::cpp_function::cpp_function(Return (*)(Args ...), const Extra& ...) [with Return = int; Args = {unsigned char**, int*, int*}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [28]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:813:22: required from ‘pybind11::module& pybind11::module::def(const char*, Func&&, const Extra& ...) [with Func = int (*)(unsigned char**, int*, int*); Extra = {char [28]}]’ imagopy/cbinding/imagopy.cpp:110:40: required from here /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h:1874:37: error: cannot convert ‘pybind11::detail::type_caster<unsigned char, void>::cast_op_type<unsigned char**&&> {aka unsigned char*}’ to ‘unsigned char**’ in argument passing /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h: In instantiation of ‘Return pybind11::detail::argument_loader<Args>::call_impl(Func&&, pybind11::detail::index_sequence<Is ...>, Guard&&) [with Return = int; Func = int (*&)(int, char**, int*, char**); long unsigned int ...Is = {0, 1, 2, 3}; Guard = pybind11::detail::void_type; Args = {int, char**, int*, char**}]’: /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h:1851:101: required from ‘pybind11::detail::enable_if_t<(! std::is_void<_Yp>::value), Return> pybind11::detail::argument_loader<Args>::call(Func&&) && [with Return = int; Guard = pybind11::detail::void_type; Func = int (*&)(int, char**, int*, char**); Args = {int, char**, int*, char**}; pybind11::detail::enable_if_t<(! std::is_void<_Yp>::value), Return> = int]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:154:43: required from ‘pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...)::<lambda(pybind11::detail::function_call&)> [with Func = int (*&)(int, char**, int*, char**); Return = int; Args = {int, char**, int*, char**}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [43]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:132:22: required from ‘struct pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = int (*&)(int, char**, int*, char**); Return = int; Args = {int, char**, int*, char**}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [43]}]::<lambda(struct pybind11::detail::function_call&)>’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:132:19: required from ‘void pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = int (*&)(int, char**, int*, char**); Return = int; Args = {int, char**, int*, char**}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [43]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:58:9: required from ‘pybind11::cpp_function::cpp_function(Return (*)(Args ...), const Extra& ...) [with Return = int; Args = {int, char**, int*, char**}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, char [43]}]’ /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/pybind11.h:813:22: required from ‘pybind11::module& pybind11::module::def(const char*, Func&&, const Extra& ...) [with Func = int (*)(int, char**, int*, char**); Extra = {char [43]}]’ imagopy/cbinding/imagopy.cpp:118:55: required from here /home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h:1874:37: error: cannot convert ‘pybind11::detail::type_caster<char, void>::cast_op_type<char**&&> {aka char*}’ to ‘char**’ in argument passing error: command 'gcc' failed with exit status 1
The error line has:
/home/bbrighttaer/anaconda3/include/python3.6m/pybind11/cast.h:1874:37: error: cannot convert ‘pybind11::detail::type_caster<char, void>::cast_op_type<char**&&> {aka char*}’ to ‘char**’ in argument passing
I am using pybind11==2.2.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants