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

Separate types required for low-level API from high-level functionality #688

Merged
merged 6 commits into from
Oct 5, 2020

Conversation

jmert
Copy link
Contributor

@jmert jmert commented Oct 3, 2020

This PR does two major things:

  1. It moves all of the types and constants required to call the low-level C functions into a new file src/api_types.jl.
  2. A few more types are renamed to match the C names, as was done in Rename HDF5 constants to C definitions for consistency #678.

This resolves the bulk of what I see as the outstanding reorganization aiming at separating the low-level and high-level interfaces. One of the outstanding items is the definition and use of HDF5ReferenceObj, which in this PR is left alone and still straddles divide. I've got a second PR I'll be putting up where I also take a stab at disentangling that, but since it's not a trivial operation, I thought I'd present them separately.

ctime::C_time_t
btime::C_time_t
num_attrs::hsize_t
#{ inlined struct H5O_hdr_info_t named type
Copy link
Contributor

Choose a reason for hiding this comment

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

I remember looking at this before and thinking that this inlining seems to directly contradict the documentation. I know you didn't do this, but I'm just raising the point now since you added the nice comments and made me think of it again. Do we know if this actually works or if the alignment is messed up?

Copy link
Contributor

@kleinhenz kleinhenz Oct 4, 2020

Choose a reason for hiding this comment

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

This shouldn't be a blocker for merging since this PR doesn't change anything. It just made me think of this question that I didn't have the motivation to figure out last time I saw it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that should work — the structure has size and alignment equal to the members, so inlining them shouldn't change that. As a concrete check:

julia> using HDF5

julia> Int(fieldoffset(HDF5.H5O_info_t, fieldcount(HDF5.H5O_info_t)))
144

which can be compared against the offsetof(H5O_info1_t, meta_size.attr); computed in C: godbolt which calculates it as 144 as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, just read the link you had to the docs. Maybe the saving grace here is that the sum of the inlined members' sizes correspond to an alignment offset already, so there's no padding to worry about?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not opposed to making the fields a separate struct to follow the C API, though.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not opposed to making the fields a separate struct to follow the C API, though.

Probably a better idea.

Looking at the docs, I don't think there's an alignment issue here. The result should be the same if we defined the fields in a separate (immutable) struct. @kleinhenz was there something specific that lead you to believe there was an alignment issue to begin with?

Copy link
Contributor

Choose a reason for hiding this comment

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

No I haven't noticed any problems, although I think this part of the code is not exercised in the tests much. I just noticed that this does what the julia documentation makes a point of saying not to do, but I am definitely not an expert on this kind of thing even in c.

Copy link
Member

Choose a reason for hiding this comment

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

The documentation reads wrong to me?

This doesn't make sense to me

When mirroring a struct used by-value inside another struct in C, it is imperative that you do not attempt to manually copy the fields over, as this will not preserve the correct field alignment.

from the docs at https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#Struct-Type-Correspondences

To me this reads as telling us that we should not mirror

typedef struct {
    int a;
    double b;
} A;

typedef struct {
    A a;
    A b;
    int c;
} B;

But AFAIK it's perfectly correct to mirror this in Julia as follows:

struct A
    a::Cint
    b::Cdouble
end

struct B
    a::A
    b::A
    c::Cint
end

## or even

struct B
    a1::Cint
    b1::Cdouble
    a2::Cint
    b2::Cdouble
    c::Cint
end

and retain correct alignment

Copy link
Member

Choose a reason for hiding this comment

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

For reference I've also been referred to : https://github.com/analytech-solutions/CBinding.jl and JuliaLang/julia#33120 regarding these issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I came across CBinding.jl and CBindingGen.jl yesterday. My quick/inexpert thought is that it's maybe too heavy for what we want here — it generated a large file of a bunch of macro definitions that took quite a while to precompile and load. Doing it manually seems to give much shorter load time.

That said, I've got a very rough use of Clang.jl's generator running — not well enough that it can actually auto-generate the bindings for us, but enough that it can be a useful point of comparison (and very fast way to replace all the list of consts with enums if desired).

Copy link
Member

@musm musm left a comment

Choose a reason for hiding this comment

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

LGTM! Good re-org, I just had one minor comment then I will merge after that.

src/api_types.jl Outdated Show resolved Hide resolved
src/api_types.jl Show resolved Hide resolved
src/api_types.jl Outdated Show resolved Hide resolved
gen/api_defs.jl Outdated Show resolved Hide resolved
@musm
Copy link
Member

musm commented Oct 5, 2020

LGTM, I think I will squash this if OK.

@musm musm merged commit 1ca2b72 into JuliaIO:master Oct 5, 2020
@jmert jmert deleted the api_types branch October 5, 2020 15:34
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

Successfully merging this pull request may close these issues.

3 participants