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

Error on undefined typedef union #214

Closed
rschwarz opened this issue Dec 14, 2018 · 8 comments
Closed

Error on undefined typedef union #214

rschwarz opened this issue Dec 14, 2018 · 8 comments

Comments

@rschwarz
Copy link

I have something like this in my C header (similar to #58):

typedef union secretunion SECRET;

When I try to wrap this, I actually get an error:

[ Info: Error thrown. Last cursor available in Clang.wrap_c.debug_cursors
ERROR: LoadError: BoundsError: attempt to access 0-element Array{Clang.cindex.CLCursor,1} at index [0]
Stacktrace:
 [1] getindex at ./array.jl:731 [inlined]
 [2] largestfield(::Clang.cindex.UnionDecl) at Clang/src/wrap_c.jl:312
 [...]
 [5] wrap(::Clang.wrap_c.WrapContext, ::OrderedCollections.OrderedDict{Symbol,Clang.wrap_c.ExprUnit}, ::Clang.cindex.UnionDecl) at Clang/src/wrap_c.jl:436
 [6] wrap_header(::Clang.wrap_c.WrapContext, ::Clang.cindex.TranslationUnit, ::String, ::Array{Any,1}) at Clang/src/wrap_c.jl:685
 [...]

The problem seems to be that largestfield tries to return access fields[0] while fields is actually empty:

function largestfield(cu::UnionDecl)
    maxsize,maxelem = 0,0
    fields = children(cu)
    for i in 1:length(fields)
        field_size = typesize(cu_type(fields[i]))
        if field_size > maxsize
            maxsize = field_size
            maxelem = i
        end
    end
    fields[maxelem]
end
@rschwarz
Copy link
Author

Maybe related to #55.

@Gnimuc
Copy link
Member

Gnimuc commented Dec 15, 2018

that's because opaque union typedefs were not handled correctly.

@rschwarz
Copy link
Author

Thanks for your proper fix, I will try again with your branch.

@rschwarz
Copy link
Author

@Gnimuc I tried running my script again using your branch refactor. I modified it a bit to look like the example you give in the README.md:

wc = Clang.init(
    headers=[joinpath(header_path, h) for h in headers],
    header_wrapped = (root, current) -> root == current,
    header_library = x -> "libscip",
    common_file="common.jl",
    output_dir="../src/wrapper",
    clang_includes = vcat(LIBCLANG_INCLUDE, LLVM_INCLUDE),
    clang_args = ["-I", joinpath(LIBCLANG_INCLUDE, "..")],
    clang_diagnostics = true,
)

Clang.run(wc)

Here, headers will contain absolute paths to the header files. When I run this, I get an error right in the beginning (for the first header file in the array):

[ Info: wrapping header: /usr/include/scip/type_retcode.h ...
ERROR: LoadError: ArgumentError: invalid index: /usr/include/scip/type_retcode.h of type String
Stacktrace:
 [1] to_index(::String) at ./indices.jl:265
 [2] to_index(::Array{TranslationUnit,1}, ::String) at ./indices.jl:247
 [3] to_indices at ./indices.jl:293 [inlined]
 [4] to_indices at ./indices.jl:290 [inlined]
 [5] getindex at ./abstractarray.jl:905 [inlined]
 [6] run(::WrapContext) at /home/rs/.julia/dev/Clang/src/compat.jl:100

The line at level 6 is indeed a little strange: In ctx.trans_units[header], header is a String, while ctx.trans_units is an Array. How could it be used as an index?

Maybe I got something wrong, but I could not find an example or test that uses init and run like in the README.

@Gnimuc
Copy link
Member

Gnimuc commented Dec 15, 2018

oh, nice catch. I forgot to update the run(wc::WrapContext) function. a2c95f9

@leethargo init and run are old high-level APIs. If you'd like to know what Clang does under the hood, please take a look at this tutorial. The generator script of Clang.jl is also a good example on how to use Clang.

@Gnimuc
Copy link
Member

Gnimuc commented Dec 15, 2018

note, you should replace LIBCLANG_INCLUDE with your lib's header path:

wc = Clang.init(
    headers=[joinpath(header_path, h) for h in headers],
    header_wrapped = (root, current) -> root == current,
    header_library = x -> "libscip",
    common_file="common.jl",
    output_dir="../src/wrapper",
    clang_includes = vcat(header_path, LLVM_INCLUDE),
    clang_args = ["-I", header_path],
    clang_diagnostics = true,
)

rschwarz added a commit to scipopt/SCIP.jl that referenced this issue Dec 15, 2018
@rschwarz
Copy link
Author

Thanks again. I might look into the tutorial later, when I need more fine-grained control, but your snippet already helped me generate a wrapper for the whole set of headers I care about!

I thought that LIBCLANG_INCLUDE was needed to provide stdef.h and similar, but I guess that LLVM_INCLUDE will do that then.

@Gnimuc
Copy link
Member

Gnimuc commented Dec 16, 2018

I thought that LIBCLANG_INCLUDE was needed to provide stdef.h and similar, but I guess that LLVM_INCLUDE will do that then.

Exactly.

Here is another hint for generating a template wrapper project:

copydeps(dirname(api_file))
print_template(joinpath(dirname(api_file), "LibTemplate.jl"))

@Gnimuc Gnimuc pinned this issue Dec 16, 2018
@Gnimuc Gnimuc unpinned this issue Dec 16, 2018
@Gnimuc Gnimuc closed this as completed in 79ab2d0 Dec 23, 2018
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 a pull request may close this issue.

2 participants