Clang.jl wrapper generation warnings/missing parts


I’m trying to wrap this this GraphBLAS.h file using Clang.jl (There is already a wrapper package, but I want to try generating it automatically). I used this code:

const z = "/usr/lib/clang/9.0.0/include"
const y = "/home/Wimmerer/Desktop/GraphBLAS-3.1.1/Include/GraphBLAS.h"
wc = init(;headers= [y], output_file=joinpath(@__DIR__,"libGB_api.jl"),common_file = joinpath(@__DIR__,"libGB_common.jl"),clang_includes = vcat([y],[z]), header_wrapped = (root,current)->root == current,header_library = x->"libGB",clang_diagnostics = true)

Unfortunately while I get most ordinary functions wrapped I do have quite a few warnings and missing bits. In particular I get:

┌ Warning: not wrapping CLCursor (CLLastPreprocessing) stdio.h
└ @ Clang ~/.julia/packages/Clang/CiPzM/src/wrap_c.jl:443

for all the standard libs required by GraphBLAS: errno, string, stdlib, stdbool, stdint, inttypes, stddef, limits, math, stdarg

┌ Warning: not wrapping CLCursor (CLMacroInstantiation) bool
└ @ Clang ~/.julia/packages/Clang/CiPzM/src/wrap_c.jl:443

Repeated many times for bool, as well as GxB_NTHREADS, and GxB_CHUNK
And finally:

┌ Warning: not wrapping CLCursor (CLVarDecl) GrB_BOOL
└ @ Clang ~/.julia/packages/Clang/CiPzM/src/wrap_c.jl:443

for everything under the extern keyword in the .h file.

I’m not well versed enough in C programming and linking to external libraries to diagnose these issues myself unfortunately. I would appreciate any pointers here!
The Clang.jl docs have a great example, but not much to go off of if it doesn’t map well to my particular problems.

Not all of the code in the header file are useful for generating Julia wrapper. It’s very tricky to handle macros correctly. For now, Clang.jl only provides partially support for those “constant definition macros” such as #define GxB_IMPLEMENTATION_NAME "SuiteSparse:GraphBLAS". Many of those warnings can be safely ignored. If you’re wrapping some C headers with “weird” macros, it’s inevitable to fix those macros manually.

It looks like many new users are quite confused by those warnings, maybe it’s not a good idea to explicitly warn everything.

This warning is for #include stdio.h. We don’t need to do anything to handle it.

IIRC, those macro CLMacroInstantiations have already been automatically expanded. No special handling is needed here. But I’m not sure whether all kinds of the CLMacroInstantiations can be safely ignored or not.

Actually, those externs are not used anywhere in the APIs.

I’ll run some tests, all the core functions seem present!

Actually, those externs are not used anywhere in the APIs.

In the GraphBLAS API? They’re supposed to be built-in’s to make using various semirings easier to use. Although in the other wrappers I’ve seen, including Python, I’m a bit confused. All of them seem to use just uninitialized classes, just something like GxB_MIN_FIRST_INT8 = GrB_Semiring() for instance. How is the library figuring out which semiring this actually is? By constant name?

I was thinking they’re just global variables. I’m wondering what should be generated for those globals, cglobals?

1 Like

Not sure, I’m reading GraphBLAS_API_C_1.2.0.pdf now. From chapter 2.4 and 4.2.15, it looks like those semirings can firstly be declared as opaque handles and then be defined by calling Grb_semiring_new function.

I also noticed GraphBLAS use new C99 features like:

Clang.jl cannot handle this, but I guess it’s easy to rewrite these macros as pure Julia macro since Julia macro supports overloading and multiple dispatch.

Can you use dlsym for those functions? Just dlsym(libgb,"GrB_Matrix_setElement_"*TYPE)?

For the built-ins I think cglobal and dlsym should work right? GrB_Semiring_new can be used to make new semirings. But for the built in operators/monoids/semirings/types, which is what I primarily care about? I’ll test when I get home today, but to my mind that should work. Unless you can’t use dlsym with Clang.jl wrappers, although I don’t see why that would be.

So I would somehow need to check which functions/globals are missing, then load them with dlsym. That seems simple enough!

Hey ! You could try . I wrote the wrapper last summer as part of GSoC, user-defined types are not supported but the rest works fine.

1 Like

GxB_MIN_FIRST_INT8 and the like are predefined objects. That one is a semiring, and you can use it without having to do GrB_Semiring_new. GraphBLAS has 100s of builtin operators (GrB_PLUS_FP64 does x+y for two doubles, for example) and 1000s of built-in semirings.