Skip to content

Commit 2ab51e0

Browse files
committed
wrap ccalls that return Cstring in unsafe_string
1 parent 3f14643 commit 2ab51e0

File tree

3 files changed

+75
-16
lines changed

3 files changed

+75
-16
lines changed

gen/wrap_geos.jl

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,77 @@ like `GEOS_VERSION`, which are just strings, are correct.
1212
=#
1313

1414
using Clang
15+
using MacroTools
1516

1617
includedir = normpath(joinpath(@__DIR__, "..", "deps", "usr", "include"))
1718
headerfiles = [joinpath(includedir, "geos_c.h")]
1819

20+
"""
21+
Custom rewriter for Clang.jl's C wrapper
22+
23+
Gets called with all expressions in a header file, or all expressions in a common file.
24+
The expressions get sent to `rewriter(::Expr)`` for
25+
further treatment.
26+
"""
27+
function rewriter(xs::Vector)
28+
rewritten = Any[]
29+
for x in xs
30+
# Clang.jl inserts strings like "# Skipping MacroDefinition: X"
31+
# keep these to get a sense of what we are missing
32+
if x isa String
33+
push!(rewritten, x)
34+
continue
35+
end
36+
@assert x isa Expr
37+
38+
x2 = rewriter(x)
39+
push!(rewritten, x2)
40+
end
41+
rewritten
42+
end
43+
44+
"Functions that return a Cstring are wrapped in unsafe_string to return a String"
45+
function rewriter(x::Expr)
46+
if @capture(x,
47+
function f_(fargs__)
48+
ccall(fname_, rettype_, argtypes_, argvalues__)
49+
end
50+
)
51+
# it is a function wrapper around a ccall
52+
53+
# bind the ccall such that we can easily wrap it
54+
cc = :(ccall($fname, $rettype, $argtypes, $(argvalues...)))
55+
56+
cc2 = if rettype == :Cstring
57+
:(unsafe_string($cc))
58+
else
59+
cc
60+
end
61+
62+
# stitch the modified function expression back together
63+
x2 = :(function $f($(fargs...))
64+
$cc2
65+
end) |> prettify
66+
x2
67+
else
68+
# do not modify expressions that are no ccall function wrappers
69+
x
70+
end
71+
end
72+
1973
wc = init(; headers = headerfiles,
20-
output_file = joinpath(@__DIR__, "geos_c.jl"),
21-
common_file = joinpath(@__DIR__, "geos_common.jl"),
74+
output_file = joinpath(@__DIR__, "..", "src", "geos_c.jl"),
75+
common_file = joinpath(@__DIR__, "..", "src", "geos_common.jl"),
2276
clang_includes = [includedir, CLANG_INCLUDE],
2377
clang_args = ["-I", includedir],
2478
header_wrapped = (root, current) -> root == current,
2579
header_library = x -> "libgeos",
2680
clang_diagnostics = true,
81+
rewriter = rewriter,
2782
)
2883

2984
run(wc)
85+
86+
# delete Clang.jl helper files
87+
rm(joinpath(@__DIR__, "..", "src", "LibTemplate.jl"))
88+
rm(joinpath(@__DIR__, "..", "src", "ctypes.jl"))

src/geos_c.jl

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ function GEOSContext_setErrorMessageHandler_r(extHandle, ef, userData)
4747
end
4848

4949
function GEOSversion()
50-
ccall((:GEOSversion, libgeos), Cstring, ())
50+
unsafe_string(ccall((:GEOSversion, libgeos), Cstring, ()))
5151
end
5252

5353
function GEOSGeomFromWKT_r(handle, wkt)
5454
ccall((:GEOSGeomFromWKT_r, libgeos), Ptr{GEOSGeometry}, (GEOSContextHandle_t, Cstring), handle, wkt)
5555
end
5656

5757
function GEOSGeomToWKT_r(handle, g)
58-
ccall((:GEOSGeomToWKT_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}), handle, g)
58+
unsafe_string(ccall((:GEOSGeomToWKT_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}), handle, g))
5959
end
6060

6161
function GEOS_getWKBOutputDims_r(handle)
@@ -523,31 +523,31 @@ function GEOSRelatePattern_r(handle, g1, g2, pat)
523523
end
524524

525525
function GEOSRelate_r(handle, g1, g2)
526-
ccall((:GEOSRelate_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}, Ptr{GEOSGeometry}), handle, g1, g2)
526+
unsafe_string(ccall((:GEOSRelate_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}, Ptr{GEOSGeometry}), handle, g1, g2))
527527
end
528528

529529
function GEOSRelatePatternMatch_r(handle, mat, pat)
530530
ccall((:GEOSRelatePatternMatch_r, libgeos), UInt8, (GEOSContextHandle_t, Cstring, Cstring), handle, mat, pat)
531531
end
532532

533533
function GEOSRelateBoundaryNodeRule_r(handle, g1, g2, bnr)
534-
ccall((:GEOSRelateBoundaryNodeRule_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}, Ptr{GEOSGeometry}, Cint), handle, g1, g2, bnr)
534+
unsafe_string(ccall((:GEOSRelateBoundaryNodeRule_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}, Ptr{GEOSGeometry}, Cint), handle, g1, g2, bnr))
535535
end
536536

537537
function GEOSisValid_r(handle, g)
538538
ccall((:GEOSisValid_r, libgeos), UInt8, (GEOSContextHandle_t, Ptr{GEOSGeometry}), handle, g)
539539
end
540540

541541
function GEOSisValidReason_r(handle, g)
542-
ccall((:GEOSisValidReason_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}), handle, g)
542+
unsafe_string(ccall((:GEOSisValidReason_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}), handle, g))
543543
end
544544

545545
function GEOSisValidDetail_r(handle, g, flags, reason, location)
546546
ccall((:GEOSisValidDetail_r, libgeos), UInt8, (GEOSContextHandle_t, Ptr{GEOSGeometry}, Cint, Ptr{Cstring}, Ptr{Ptr{GEOSGeometry}}), handle, g, flags, reason, location)
547547
end
548548

549549
function GEOSGeomType_r(handle, g)
550-
ccall((:GEOSGeomType_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}), handle, g)
550+
unsafe_string(ccall((:GEOSGeomType_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSGeometry}), handle, g))
551551
end
552552

553553
function GEOSGeomTypeId_r(handle, g)
@@ -727,7 +727,7 @@ function GEOSWKTWriter_destroy_r(handle, writer)
727727
end
728728

729729
function GEOSWKTWriter_write_r(handle, writer, g)
730-
ccall((:GEOSWKTWriter_write_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSWKTWriter}, Ptr{GEOSGeometry}), handle, writer, g)
730+
unsafe_string(ccall((:GEOSWKTWriter_write_r, libgeos), Cstring, (GEOSContextHandle_t, Ptr{GEOSWKTWriter}, Ptr{GEOSGeometry}), handle, writer, g))
731731
end
732732

733733
function GEOSWKTWriter_setTrim_r(handle, writer, trim)
@@ -823,7 +823,7 @@ function GEOSGeomFromWKT(wkt)
823823
end
824824

825825
function GEOSGeomToWKT(g)
826-
ccall((:GEOSGeomToWKT, libgeos), Cstring, (Ptr{GEOSGeometry},), g)
826+
unsafe_string(ccall((:GEOSGeomToWKT, libgeos), Cstring, (Ptr{GEOSGeometry},), g))
827827
end
828828

829829
function GEOS_getWKBOutputDims()
@@ -1291,31 +1291,31 @@ function GEOSRelatePattern(g1, g2, pat)
12911291
end
12921292

12931293
function GEOSRelate(g1, g2)
1294-
ccall((:GEOSRelate, libgeos), Cstring, (Ptr{GEOSGeometry}, Ptr{GEOSGeometry}), g1, g2)
1294+
unsafe_string(ccall((:GEOSRelate, libgeos), Cstring, (Ptr{GEOSGeometry}, Ptr{GEOSGeometry}), g1, g2))
12951295
end
12961296

12971297
function GEOSRelatePatternMatch(mat, pat)
12981298
ccall((:GEOSRelatePatternMatch, libgeos), UInt8, (Cstring, Cstring), mat, pat)
12991299
end
13001300

13011301
function GEOSRelateBoundaryNodeRule(g1, g2, bnr)
1302-
ccall((:GEOSRelateBoundaryNodeRule, libgeos), Cstring, (Ptr{GEOSGeometry}, Ptr{GEOSGeometry}, Cint), g1, g2, bnr)
1302+
unsafe_string(ccall((:GEOSRelateBoundaryNodeRule, libgeos), Cstring, (Ptr{GEOSGeometry}, Ptr{GEOSGeometry}, Cint), g1, g2, bnr))
13031303
end
13041304

13051305
function GEOSisValid(g)
13061306
ccall((:GEOSisValid, libgeos), UInt8, (Ptr{GEOSGeometry},), g)
13071307
end
13081308

13091309
function GEOSisValidReason(g)
1310-
ccall((:GEOSisValidReason, libgeos), Cstring, (Ptr{GEOSGeometry},), g)
1310+
unsafe_string(ccall((:GEOSisValidReason, libgeos), Cstring, (Ptr{GEOSGeometry},), g))
13111311
end
13121312

13131313
function GEOSisValidDetail(g, flags, reason, location)
13141314
ccall((:GEOSisValidDetail, libgeos), UInt8, (Ptr{GEOSGeometry}, Cint, Ptr{Cstring}, Ptr{Ptr{GEOSGeometry}}), g, flags, reason, location)
13151315
end
13161316

13171317
function GEOSGeomType(g)
1318-
ccall((:GEOSGeomType, libgeos), Cstring, (Ptr{GEOSGeometry},), g)
1318+
unsafe_string(ccall((:GEOSGeomType, libgeos), Cstring, (Ptr{GEOSGeometry},), g))
13191319
end
13201320

13211321
function GEOSGeomTypeId(g)
@@ -1495,7 +1495,7 @@ function GEOSWKTWriter_destroy(writer)
14951495
end
14961496

14971497
function GEOSWKTWriter_write(writer, g)
1498-
ccall((:GEOSWKTWriter_write, libgeos), Cstring, (Ptr{GEOSWKTWriter}, Ptr{GEOSGeometry}), writer, g)
1498+
unsafe_string(ccall((:GEOSWKTWriter_write, libgeos), Cstring, (Ptr{GEOSWKTWriter}, Ptr{GEOSGeometry}), writer, g))
14991499
end
15001500

15011501
function GEOSWKTWriter_setTrim(writer, trim)

src/geos_functions.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ _readgeom(wkbbuffer::Vector{Cuchar}, context::GEOSContext = _context) =
1919
_readgeom(wkbbuffer, WKBReader(context), context)
2020

2121
function _writegeom(geom::GEOSGeom, wktwriter::WKTWriter, context::GEOSContext = _context)
22-
unsafe_string(GEOSWKTWriter_write_r(context.ptr, wktwriter.ptr, geom))
22+
GEOSWKTWriter_write_r(context.ptr, wktwriter.ptr, geom)
2323
end
2424

2525
function _writegeom(geom::GEOSGeom, wkbwriter::WKBWriter, context::GEOSContext = _context)

0 commit comments

Comments
 (0)