Skip to content

ENH: Add templates for f2py c functions and handle more C types #25260

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Pranavchiku
Copy link

Closes #25229.

This PR has commits from #25226, we'll wait till it gets merged.

@HaoZeke
Copy link
Member

HaoZeke commented Dec 19, 2023

@Pranavchiku now that #25226 is in, could you rebase this and address the test failures?

@Pranavchiku Pranavchiku force-pushed the gh25229 branch 2 times, most recently from 9b71de9 to 0170e08 Compare December 22, 2023 08:45
@HaoZeke
Copy link
Member

HaoZeke commented Dec 24, 2023

@Pranavchiku, the problem is essentially in the way the c_double is being mapped. It is now incorrectly mapped to float somewhere instead of the correct double. Here are the changes from the older file (working) to the this one:

❯ diff meson_works/codditymodule.c meson_broken/codditymodule.c
2c2
<  * This file is auto-generated with f2py (version:2.0.0.dev0+git20231224.a43c068).
---
>  * This file is auto-generated with f2py (version:2.0.0.dev0+git20231222.94d21b0).
5c5
<  * Generation date: Sun Dec 24 18:19:50 2023
---
>  * Generation date: Sun Dec 24 18:24:33 2023
140a141,152
> static int
> float_from_pyobj(float* v, PyObject *obj, const char *errmess)
> {
>     double d=0.0;
>     if (double_from_pyobj(&d,obj,errmess)) {
>         *v = (float)d;
>         return 1;
>     }
>     return 0;
> }
> 
> 
170c182
<                            void (*f2py_func)(double*,double*,double*)) {
---
>                            void (*f2py_func)(float*,float*,float*)) {
175c187
<     double a = 0;
---
>     float a = 0;
177c189
<     double b = 0;
---
>     float b = 0;
179c191
<     double c = 0;
---
>     float c = 0;
192c204
<         f2py_success = double_from_pyobj(&a,a_capi,"coddity.coddity.c_add() 1st argument (a) can't be converted to double");
---
>         f2py_success = float_from_pyobj(&a,a_capi,"coddity.coddity.c_add() 1st argument (a) can't be converted to float");
195c207
<         f2py_success = double_from_pyobj(&b,b_capi,"coddity.coddity.c_add() 2nd argument (b) can't be converted to double");
---
>         f2py_success = float_from_pyobj(&b,b_capi,"coddity.coddity.c_add() 2nd argument (b) can't be converted to float");
214c226
<         capi_buildvalue = Py_BuildValue("d",c);
---
>         capi_buildvalue = Py_BuildValue("f",c);
298c310
<     s = PyUnicode_FromString("2.0.0.dev0+git20231224.a43c068");
---
>     s = PyUnicode_FromString("2.0.0.dev0+git20231222.94d21b0");
302c314
<         "This module 'coddity' is auto-generated with f2py (version:2.0.0.dev0+git20231224.a43c068).\nFunctions:\n"
---
>         "This module 'coddity' is auto-generated with f2py (version:2.0.0.dev0+git20231222.94d21b0).\nFunctions:\n"
306c318
<     s = PyUnicode_FromString("2.0.0.dev0+git20231224.a43c068");
---
>     s = PyUnicode_FromString("2.0.0.dev0+git20231222.94d21b0");

For this test case (extracted from the isoCtests.f90 file):

  module coddity
    use iso_c_binding, only: c_double, c_int, c_int64_t
    implicit none
    contains
      subroutine c_add(a, b, c) bind(c, name="c_add")
        real(c_double), intent(in) :: a, b
        real(c_double), intent(out) :: c
        c = a + b
      end subroutine c_add
  end module coddity

The steps to reproduce this (and other similar errors) is:

micromamba activate numpy-dev
spin run $SHELL
cd gh-25229 # or wherever the file is
f2py -m coddity -c coddity.f90 --build-dir blah --backend meson
# Modify the files after inspection

Another thing to do is to use meld to visually diff whole folders at once, between working and non-working variants.

Copy link
Member

@HaoZeke HaoZeke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pranavchiku almost there :) looking good so far!

Comment on lines +873 to +884
needs['int64_t_from_pyobj'] = ['long_from_pyobj']
cfuncs['int64_t_from_pyobj'] = """
static int
int64_t_from_pyobj(int64_t* v, PyObject *obj, const char *errmess) {
long i = 0;
if (long_from_pyobj(&i, obj, errmess)) {
*v = (int64_t)i;
return 1;
}
return 0;
}
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pranavchiku could you check (in light of the previous comment) which of these need to be explicitly written out and which can be just type cast? I suppose it might be best to just have each one handled explicitly, if only to get the C++ types correct in the function signatures....

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, on it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, we already have ones for float/double_complex so I skipped both. I am not sure about how to add it for bool hence skipped it.

@Pranavchiku
Copy link
Author

Thank you @HaoZeke, I'll apply code review by tonight.

@Pranavchiku
Copy link
Author

Tests pass locally for me.

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

Successfully merging this pull request may close these issues.

ENH: Add templates for f2py c functions and handle more C types
2 participants