Skip to content
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

Is there a straightforward way to pass numpy.float128 arguments to C++? #1785

Open
mreineck opened this issue May 10, 2019 · 6 comments
Open

Comments

@mreineck
Copy link

I'd like to pass an object of type numpy.float128 from Python to a C++ function wrapped by pybind11. My first attempt was to simply use "long double" as argument type on the C++ side, but the values I'm passing are truncated to about "double" accuracy - I expect this happens because the value is cast to a standard Python "float" somewhere on the way.

What would be the proper way to achieve this?

@eacousineau
Copy link
Contributor

TTBOMK, there may not be a straightforward "scalar" caster for NumPy types that are not directly tied to Python types (e.g. np.uint*, np.float16, etc.).

As a first step, here's showing float128 works as an array (but avoiding the scalar conversion):
eacousineau/repro@b04db11#diff-b4dfa50924d08e44f5f4cd7861a2fa26R56

Next step would be to just lie to pybind11 about the scalar, and return a scalar np.ndarray.
Will briefly try that out.

@eacousineau
Copy link
Contributor

Hm... Trying out a type_caster<float128> has proven to be a bit persnickety...
eacousineau/repro@2c30668#diff-b4dfa50924d08e44f5f4cd7861a2fa26R44

Also, through the current API, I'm not sure how to enforce a scalar ndarray vs an empty ndarray:
https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html

I'm not sure if that's what's causing the circular 'base' error...

@eacousineau
Copy link
Contributor

eacousineau commented May 11, 2019

Ah, was just not releasing references correctly.

Working code:
https://github.com/eacousineau/repro/blob/5e6acf6/python/pybind11/custom_tests/test_numpy_issue1785.cc#L103-L105

@mreineck
Copy link
Author

Thanks a lot for looking into this!

I have tried to compile your code, but got:

martin@debian:~/codes/pypocketfft$ python3 setup.py install --user -f
running install
running bdist_egg
running egg_info
writing pypocketfft.egg-info/PKG-INFO
writing dependency_links to pypocketfft.egg-info/dependency_links.txt
writing requirements to pypocketfft.egg-info/requires.txt
writing top-level names to pypocketfft.egg-info/top_level.txt
reading manifest file 'pypocketfft.egg-info/SOURCES.txt'
writing manifest file 'pypocketfft.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-x86_64/egg
running install_lib
running build_ext
building 'pypocketfft' extension
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I./ -I/usr/include/eigen3/ -I/usr/local/include/python3.7 -I/home/martin/.local/include/python3.7m -I/usr/include/python3.7m -c pypocketfft.cc -o build/temp.linux-x86_64-3.7/pypocketfft.o -march=native -O3 -Wfatal-errors -Wno-ignored-attributes --std=c++14
In file included from /home/martin/.local/include/python3.7m/pybind11/embed.h:12,
                 from pypocketfft.cc:4:
/home/martin/.local/include/python3.7m/pybind11/pybind11.h: In instantiation of ���void pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = init_module(pybind11::module)::<lambda(Vector<long double, -1>)>; Return = long double; Args = {Eigen::Matrix<long double, -1, 1, 0, -1, 1>}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling}]���:
/home/martin/.local/include/python3.7m/pybind11/pybind11.h:65:9:   required from ���pybind11::cpp_function::cpp_function(Func&&, const Extra& ...) [with Func = init_module(pybind11::module)::<lambda(Vector<long double, -1>)>; Extra = {pybind11::name, pybind11::scope, pybind11::sibling}; <template-parameter-1-3> = void]���
/home/martin/.local/include/python3.7m/pybind11/pybind11.h:813:22:   required from ���pybind11::module& pybind11::module::def(const char*, Func&&, const Extra& ...) [with Func = init_module(pybind11::module)::<lambda(Vector<long double, -1>)>; Extra = {}]���
pypocketfft.cc:62:4:   required from here
/home/martin/.local/include/python3.7m/pybind11/pybind11.h:167:95: error: no match for call to ���(const pybind11::detail::descr<8, 0>) ()���
         PYBIND11_DESCR signature = _("(") + cast_in::arg_names() + _(") -> ") + cast_out::name();
                                                                                 ~~~~~~~~~~~~~~^~
compilation terminated due to -Wfatal-errors.
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

(Don't worry about the file names, I just replaced my C++ code with your file.)
Should I be using the current git HEAD of pybind11 instead of 2.2.4?

@eacousineau
Copy link
Contributor

Oops! Sorry I didn't see this earlier!

Huh... TBH, I dunno... I've hacked around with doing custom dtypes, and I didn't have to make name a function...

However, @a-sevin also ran into that same thing here:
#1776 (comment)

Are you right at v2.2.4?

@mreineck
Copy link
Author

Are you right at v2.2.4?

Yes, to the best of my knowledge.

I probably won't be able to require Eigen on the target machines, so I guess I'll have to wait anyway until "native" support materializes in pybind11. Luckily this is not a terribly important feature for me, more of a "nice-to-have" :)

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

2 participants