Skip to content

Commit 177e7c8

Browse files
committed
Generate API, convert two examples from C to Julia
1 parent 68f525e commit 177e7c8

File tree

12 files changed

+6291
-1
lines changed

12 files changed

+6291
-1
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
/Manifest*.toml
1+
Manifest*.toml
2+
*.xlsx

Project.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name = "LibXLSXWriter"
2+
uuid = "d9c5391f-cdb8-42e0-9032-91a2542ec5a4"
3+
authors = ["Jaakko Ruohio [email protected]"]
4+
version = "0.1.0-DEV"
5+
6+
[deps]
7+
CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82"
8+
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
9+
libxlsxwriter_jll = "90251a59-ee77-57fd-870b-ce07edc5a5b6"
10+
11+
[compat]
12+
CEnum = "0.5"
13+
julia = "1.10"
14+
libxlsxwriter_jll = "1.1.9"
15+
16+
[extras]
17+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
18+
19+
[targets]
20+
test = ["Test"]

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# LibXLSXWriter
2+
3+
Julia wrapper for [libxlsxwriter_jll](https://github.com/JuliaBinaryWrappers/libxlsxwriter_jll.jl). [libxlsxwriter](https://github.com/jmcnamara/libxlsxwriter) is a C library for creating Excel XLSX files.
4+
5+
[![Build Status](https://github.com/jaakkor2/LibXLSXWriter.jl/actions/workflows/CI.yml/badge.svg?branch=master)](https://github.com/jaakkor2/LibXLSXWriter.jl/actions/workflows/CI.yml?query=branch%3Amaster)

gen/Project.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[deps]
2+
Clang = "40e3b903-d033-50b4-a0cc-940c62c95e31"
3+
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
4+
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
5+
libxlsxwriter_jll = "90251a59-ee77-57fd-870b-ce07edc5a5b6"

gen/generator.jl

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using Clang.Generators
2+
using Clang
3+
using MacroTools
4+
using libxlsxwriter_jll
5+
using JuliaFormatter: format
6+
7+
function return_type_is_const_char(cursor::Clang.CLFunctionDecl)
8+
result_type = Clang.getCanonicalType(Clang.getCursorResultType(cursor))
9+
if result_type isa CLPointer
10+
destination = Clang.getPointeeType(result_type)
11+
return destination isa CLChar_S && Clang.isConstQualifiedType(destination)
12+
end
13+
return false
14+
end
15+
16+
"Functions that return a Cstring are wrapped in unsafe_string to return a String"
17+
function rewrite(ex::Expr, cursor::Clang.CLFunctionDecl)
18+
if @capture(ex, function fname_(fargs__)
19+
@ccall lib_.cname_(cargs__)::rettype_
20+
end)
21+
# bind the ccall such that we can easily wrap it
22+
cc = :(@ccall $lib.$cname($(cargs...))::$rettype)
23+
24+
cc′ = if rettype == :Cstring
25+
# do not try to free a const char *
26+
if return_type_is_const_char(cursor)
27+
:(unsafe_string($cc))
28+
else
29+
if endswith(string(cname), "_r")
30+
:(string_copy_free($cc, handle))
31+
else
32+
:(string_copy_free($cc))
33+
end
34+
end
35+
else
36+
cc
37+
end
38+
39+
# stitch the modified function expression back together
40+
f = :(function $fname($(fargs...))
41+
$cc′
42+
end) |> prettify
43+
44+
return f
45+
end
46+
return ex
47+
end
48+
49+
function rewrite!(dag::ExprDAG)
50+
for n in dag.nodes
51+
if !isa(n.cursor, Clang.CLFunctionDecl)
52+
continue
53+
end
54+
map!(e -> rewrite(e, n.cursor), n.exprs, n.exprs)
55+
end
56+
end
57+
58+
cd(@__DIR__)
59+
60+
include_dir = joinpath(libxlsxwriter_jll.artifact_dir, "include") |> normpath
61+
62+
# wrapper generator options
63+
options = load_options(joinpath(@__DIR__, "generator.toml"))
64+
65+
args = get_default_args()
66+
push!(args, "-I$include_dir")
67+
68+
header_dir = include_dir
69+
headers = [joinpath(header_dir, "xlsxwriter.h")]
70+
71+
# create context
72+
ctx = create_context(headers, args, options)
73+
74+
# run generator
75+
build!(ctx, BUILDSTAGE_NO_PRINTING)
76+
rewrite!(ctx.dag)
77+
build!(ctx, BUILDSTAGE_PRINTING_ONLY)
78+
79+
# run JuliaFormatter on the whole package
80+
format(joinpath(@__DIR__, ".."))

gen/generator.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[general]
2+
library_name = "libxlsxwriter"
3+
output_file_path = "../src/generated/libxlsxwriter_api.jl"
4+
# prologue_file_path = "prologue.jl"
5+
use_julia_native_enum_type = false
6+
print_using_CEnum = false
7+
use_deterministic_symbol = true
8+
is_local_header_only = true
9+
smart_de_anonymize = true
10+
printer_blacklist = [
11+
]
12+
[codegen]
13+
use_ccall_macro = true
14+
use_julia_bool = true
15+
always_NUL_terminated_string = true
16+
is_function_strictly_typed = false
17+
opaque_func_arg_as_PtrCvoid = false
18+
opaque_as_mutable_struct = false

src/LibXLSXWriter.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module LibXLSXWriter
2+
3+
using libxlsxwriter_jll
4+
using CEnum
5+
using Printf
6+
7+
include("generated/libxlsxwriter_api.jl")
8+
9+
lxw_chart_fill(; color=0x0, none=0x0, transparency=0x0) = lxw_chart_fill(color, none, transparency)
10+
lxw_chart_line(; color=0x0, none=0x0, width=0.0, dash_type=0x0, transparency=0x0) = lxw_chart_line(color, none, width, dash_type, transparency)
11+
lxw_chart_pattern(; fg_color=0x0, bg_color=0x0, type=0x0) = lxw_chart_pattern(fg_color, bg_color, type)
12+
lxw_chart_point(; line=lxw_chart_line(), fill=lxw_chart_fill(), pattern=lxw_chart_pattern()) = lxw_chart_point(Ptr{line}(), Ptr{fill}(), Ptr{pattern}())
13+
14+
# utility.h
15+
CELL(cell) = lxw_name_to_row(cell), lxw_name_to_col(cell)
16+
COLS(cols) = lxw_name_to_col(cols), lxw_name_to_col_2(cols)
17+
RANGE(range) = lxw_name_to_row(range), lxw_name_to_col(range), lxw_name_to_row_2(range), lxw_name_to_col_2(range)
18+
19+
# for n in names(@__MODULE__; all=true)
20+
# if Base.isidentifier(n) && n ∉ (Symbol(@__MODULE__), :eval, :include)
21+
# @eval export $n
22+
# end
23+
# end
24+
25+
end

0 commit comments

Comments
 (0)