@@ -3,7 +3,7 @@ struct CProject
3
3
headerbase:: String
4
4
end
5
5
6
- function wrapper (dest:: CProject , entrypoints, typedescs)
6
+ function wrapper (dest:: CProject , entrypoints, typedescs, forwarddecls )
7
7
# Write the header file for C
8
8
headerfile = joinpath (dest. dir, dest. headerbase * " .h" )
9
9
libvar = " JULIALIB_" * uppercase (dest. headerbase) * " _H"
@@ -15,14 +15,31 @@ function wrapper(dest::CProject, entrypoints, typedescs)
15
15
println (f, " #include <stdbool.h>" )
16
16
println (f)
17
17
18
- typedict = Dict {String, String} ()
19
- for type in values (typedescs)
20
- println (f, " typedef struct {" )
21
- for field in type. fields
22
- ft = mangle_c! (typedict, field. type)
23
- println (f, " " , ft, " " , field. name, " ;" )
18
+ typedict = Dict {Int, String} ()
19
+
20
+ # Print forward-declarations (if any, for recursive types)
21
+ for id in forwarddecls
22
+ type = typedescs[id]
23
+ @assert type isa StructDesc " un-expected forward declaration type"
24
+ mangled_name = mangle_c! (typedict, id, typedescs)
25
+ println (f, " struct " , mangled_name, " ;" )
26
+ end
27
+
28
+ # Print the struct definitions
29
+ for (id, type) in pairs (typedescs)
30
+ if type isa StructDesc
31
+ mangled_name = mangle_c! (typedict, id, typedescs)
32
+ println (f, " typedef struct " , mangled_name, " {" )
33
+ for field in type. fields
34
+ ft = mangle_c! (typedict, field. type, typedescs)
35
+ println (f, " " , ft, " " , sanitize_for_c (field. name), " ;" )
36
+ end
37
+ println (f, " } " , mangled_name, " ;" )
38
+ elseif type isa PrimitiveTypeDesc
39
+ # We only rely on built-in primitive types (c.f. `ctypes`)
40
+ elseif type isa PointerDesc
41
+ # We emit pointer types in-line - no need for a separate typedef
24
42
end
25
- println (f, " } " , mangle_c! (typedict, type. name), " ;" )
26
43
end
27
44
println (f)
28
45
@@ -31,16 +48,17 @@ function wrapper(dest::CProject, entrypoints, typedescs)
31
48
if ! isempty (args)
32
49
args = " , " * args
33
50
end
34
- print (f, mangle_c! (typedict, method. return_type), " " , method. name, " (" )
51
+ mangled_rt = mangle_c! (typedict, method. return_type, typedescs)
52
+ print (f, mangled_rt, " " , method. symbol, " (" )
35
53
isfirst = true
36
54
for arg in method. args
37
55
if isfirst
38
56
isfirst = false
39
57
else
40
58
print (f, " , " )
41
59
end
42
- ft = mangle_c! (typedict, arg. type)
43
- print (f, ft, " " , arg. name)
60
+ ft = mangle_c! (typedict, arg. type, typedescs )
61
+ print (f, ft, " " , sanitize_for_c ( arg. name) )
44
62
if arg. isva
45
63
print (f, " ..." )
46
64
end
@@ -63,7 +81,16 @@ const ctypes = Dict{String, String}(
63
81
" UInt64" => " uint64_t" ,
64
82
" Float32" => " float" ,
65
83
" Float64" => " double" ,
66
- " Bool" => " _Bool" ,
84
+ " Bool" => " bool" ,
85
+ " RawFD" => " int" ,
86
+
87
+ " Cstring" => " char *" ,
88
+ " Cwstring" => " wchar_t *" ,
89
+
90
+ # Note: These types will never appear in an auto-exported ABI, since they are not
91
+ # distinct Julia types (these are just platform-specific aliases to the types above).
92
+ " Cchar" => " char" ,
93
+ " Cwchar_t" => " wchar_t" ,
67
94
" Cvoid" => " void" ,
68
95
" Cint" => " int" ,
69
96
" Cshort" => " short" ,
@@ -73,38 +100,29 @@ const ctypes = Dict{String, String}(
73
100
" Culong" => " unsigned long" ,
74
101
" Cssize_t" => " ssize_t" ,
75
102
" Csize_t" => " size_t" ,
76
- " Cchar" => " char" ,
77
- " Cwchar_t" => " wchar_t" ,
78
- " Cstring" => " char *" ,
79
- " Cwstring" => " wchar_t *" ,
80
- " RawFD" => " int" ,
81
103
)
82
104
83
- function mangle_c! (typedict:: Dict{String, String} , type:: AbstractString )
84
- ft = get (typedict, type, nothing )
85
- ft != = nothing && return ft
86
- ft = get (ctypes, type, nothing )
87
- ft != = nothing && return ft
88
- idxbad = findfirst (r" [^a-zA-Z0-9_\{\} ]" , type)
89
- if idxbad != = nothing
90
- error (" Invalid type name: " , type, " (invalid character at position " , idxbad, " )" )
91
- end
92
- m = match (r" ^Ptr\{ (.+)\} $" , type)
93
- if m != = nothing
94
- inner_type = m. captures[1 ]
95
- result = mangle_c! (typedict, inner_type) * " *"
96
- typedict[type] = result
97
- return result
105
+ function sanitize_for_c (str:: AbstractString )
106
+ # Replace any non alphanumeric characters with '_'
107
+ return replace (str, r" [^a-zA-Z0-9_]" => " _" )
108
+ end
109
+
110
+ function mangle_c! (typedict:: Dict{Int, String} , type_id:: Int , typedescs:: OrderedDict{Int,TypeDesc} )
111
+ if type_id in keys (typedict)
112
+ return typedict[type_id]
98
113
end
99
- m = match (r" ^(.+)\{ (.+)\} $" , type)
100
- if m != = nothing
101
- basename, params = m. captures
102
- params = split (params, " ," )
103
- params = join (map (p -> mangle_c! (typedict, p), params), " _" )
104
- result = basename * " _" * params * " _"
105
- typedict[type] = result
106
- return result
114
+
115
+ type = typedescs[type_id]
116
+ if type isa PrimitiveTypeDesc
117
+ if ! in (type. name, keys (ctypes))
118
+ error (" unsupported primitive type: '$(type. name) '" )
119
+ end
120
+ return ctypes[type. name]
121
+ elseif type isa PointerDesc
122
+ mangled = mangle_c! (typedict, type. pointee_type, typedescs) * " *"
123
+ elseif type isa StructDesc
124
+ mangled = sanitize_for_c (type. name)
107
125
end
108
- typedict[type ] = type
109
- return type
126
+ typedict[type_id ] = mangled
127
+ return mangled
110
128
end
0 commit comments