Skip to content

Commit fff8ac8

Browse files
amontoisontmigot
andauthored
Generate Julia wrappers with Clang.jl (#332)
* Generate Julia wrappers with Clang.jl * Don't use the wrappers in this PR * Apply suggestions from code review Co-authored-by: Tangi Migot <tangi.migot@gmail.com> --------- Co-authored-by: Tangi Migot <tangi.migot@gmail.com>
1 parent d948fe5 commit fff8ac8

File tree

7 files changed

+1092
-5
lines changed

7 files changed

+1092
-5
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@ deps/*
88

99
docs/build
1010
docs/site
11-
dos/Manifest.toml
11+
docs/Manifest.toml
12+
13+
gen/Manifest.toml
14+

gen/Project.toml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[deps]
2+
Clang = "40e3b903-d033-50b4-a0cc-940c62c95e31"
3+
CUTEst_jll = "bb5f6f25-f23d-57fd-8f90-3ef7bad1d825"
4+
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
5+
6+
[compat]
7+
julia = "1.6"
8+
CUTEst_jll = "2.2.0"

gen/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Wrapping headers
2+
3+
This directory contains a script that can be used to automatically generate wrappers from C headers provided by CUTEst.
4+
This is done using Clang.jl.
5+
6+
# Usage
7+
8+
Either run `julia wrapper.jl` directly, or include it and call the `main()` function.
9+
Be sure to activate the project environment in this folder (`julia --project`), which will install `Clang.jl` and `JuliaFormatter.jl`.

gen/cutest.toml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[general]
2+
use_julia_native_enum_type = true
3+
print_using_CEnum = false
4+
library_name = "cutest_lib_path"
5+
6+
[codegen]
7+
use_julia_bool = true
8+
always_NUL_terminated_string = false
9+
use_ccall_macro = true
10+
11+
[codegen.macro]
12+
macro_mode = "disable"

gen/wrapper.jl

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Script to parse CUTEst headers and generate Julia wrappers.
2+
using CUTEst_jll
3+
using Clang
4+
using Clang.Generators
5+
using JuliaFormatter
6+
7+
function main()
8+
9+
cd(@__DIR__)
10+
include_dir = joinpath(CUTEst_jll.artifact_dir, "include")
11+
headers = map(header -> joinpath(include_dir, header), ["cutest.h"])
12+
13+
options = load_options(joinpath(@__DIR__, "cutest.toml"))
14+
options["general"]["output_file_path"] = joinpath("..", "src", "libcutest.jl")
15+
options["general"]["output_ignorelist"] = ["integer", "real", "doublereal", "logical", "rp_", "rpc_", "ip_", "ipc_"]
16+
17+
args = get_default_args()
18+
push!(args, "-I$include_dir")
19+
20+
ctx = create_context(headers, args, options)
21+
build!(ctx)
22+
23+
path = options["general"]["output_file_path"]
24+
code = read(path, String)
25+
code = replace(code, "Ptr{integer}" => "Ptr{Cint}")
26+
code = replace(code, "Ptr{doublereal}" => "Ptr{Float64}")
27+
code = replace(code, "Ptr{real}" => "Ptr{Float32}")
28+
code = replace(code, "Ptr{doubleCfloat}" => "Ptr{Float64}")
29+
code = replace(code, "Ptr{logical}" => "Ptr{Bool}")
30+
code = replace(code, "Ptr{rp_}" => "Ptr{Float64}")
31+
code = replace(code, "Ptr{rpc_}" => "Ptr{Float64}")
32+
code = replace(code, "Ptr{ip_}" => "Ptr{Cint}")
33+
code = replace(code, "Ptr{ipc_}" => "Ptr{Cint}")
34+
write(path, code)
35+
36+
format_file(path, YASStyle())
37+
38+
return nothing
39+
end
40+
41+
# If we want to use the file as a script with `julia wrapper.jl`
42+
if abspath(PROGRAM_FILE) == @__FILE__
43+
main()
44+
end

src/CUTEst.jl

+7-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ using Libdl
1313
using NLPModels
1414
import Libdl.dlsym
1515

16+
global cutest_lib_path = ""
17+
global cutest_lib = C_NULL
18+
include("libcutest.jl")
19+
1620
# Only one problem can be interfaced at any given time.
1721
global cutest_instances = 0
1822

@@ -64,7 +68,6 @@ end
6468

6569
const cutest_problems_path = joinpath(dirname(@__FILE__), "..", "deps", "files")
6670
isdir(cutest_problems_path) || mkpath(cutest_problems_path)
67-
global cutest_lib = C_NULL
6871

6972
function __init__()
7073
if success(`bash -c "type gfortran"`)
@@ -215,8 +218,8 @@ function sifdecoder(
215218
end
216219
run(`mv OUTSDIF.d $outsdif`)
217220
delete_temp_files(suffix)
218-
global cutest_lib =
219-
Libdl.dlopen(libname, Libdl.RTLD_NOW | Libdl.RTLD_DEEPBIND | Libdl.RTLD_GLOBAL)
221+
global cutest_lib = Libdl.dlopen(libname, Libdl.RTLD_NOW | Libdl.RTLD_DEEPBIND | Libdl.RTLD_GLOBAL)
222+
global cutest_lib_path = joinpath(cutest_problems_path, "$libname.$(Libdl.dlext)")
220223
end
221224
end
222225
rm(outlog)
@@ -298,7 +301,7 @@ function CUTEstModel(
298301
dlsym(cutest_lib, :fortran_open_),
299302
Nothing,
300303
(Ref{Int32}, Ptr{UInt8}, Ptr{Int32}),
301-
funit,
304+
[funit],
302305
outsdif,
303306
io_err,
304307
)

0 commit comments

Comments
 (0)