-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generate bindings for zmq.h using Clang.jl
Along with some extra methods we need for the Message type.
- Loading branch information
1 parent
e889c90
commit 8bd2352
Showing
6 changed files
with
849 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[deps] | ||
Clang = "40e3b903-d033-50b4-a0cc-940c62c95e31" | ||
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" | ||
ZeroMQ_jll = "8f1865be-045e-5c20-9c9f-bfbfb0764568" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import Clang | ||
import ZeroMQ_jll | ||
import MacroTools: @capture, postwalk, prettify | ||
|
||
|
||
# Helper function to look through all the generated bindings and create new | ||
# zmq_msg_* methods for the Message type. We need to create these overloads | ||
# because the Message type relies on _Message (i.e. lib.zmq_msg_t) under the | ||
# hood, and _Message is an immutable type so it doesn't have a stable address, | ||
# and so cannot safely be passed to a ccall. | ||
# | ||
# We get around this for _Message by always using a Ref{_Message}, but Message | ||
# is a mutable struct with a _Message as its first field. It's safe to pass a | ||
# pointer to a Message to libzmq because the address of the Message is the same | ||
# as its first field, the _Message. But to do that we need to create methods to | ||
# ccall libzmq with the Message type instead of lib.zmq_msg_t (_Message). | ||
function get_msg_methods(ctx, module_name) | ||
methods = Expr[] | ||
|
||
for node in ctx.dag.nodes | ||
for i in eachindex(node.exprs) | ||
expr = node.exprs[i] | ||
|
||
# Check if this is a function | ||
if @capture(expr, function name_(arg1_, args__) body_ end) | ||
# Check if it's a zmq_msg_* function | ||
if startswith(string(name), "zmq_msg_") | ||
# Replace occurrences of `arg::Ptr{zmq_msg_t}` with | ||
# `arg::Ref{Message}`. | ||
new_body = postwalk(body) do x | ||
if @capture(x, arg_name_::T_) && T == :(Ptr{zmq_msg_t}) | ||
:($arg_name::Ref{Message}) | ||
else | ||
x | ||
end | ||
end | ||
|
||
# Create the new method | ||
new_method = quote | ||
function $module_name.$name($arg1::Message, $(args...)) | ||
$new_body | ||
end | ||
end | ||
|
||
push!(methods, prettify(new_method)) | ||
end | ||
end | ||
end | ||
end | ||
|
||
return methods | ||
end | ||
|
||
cd(@__DIR__) do | ||
# Set the options | ||
options = Clang.load_options(joinpath(@__DIR__, "generator.toml")) | ||
header = joinpath(ZeroMQ_jll.artifact_dir, "include", "zmq.h") | ||
args = Clang.get_default_args() | ||
|
||
# Generate the generic bindings | ||
ctx = Clang.create_context([header], args, options) | ||
Clang.build!(ctx) | ||
|
||
# Generate the Message methods we need | ||
module_name = Symbol(options["general"]["module_name"]) | ||
msg_methods = get_msg_methods(ctx, module_name) | ||
output_file = joinpath(@__DIR__, "../src/msg_bindings.jl") | ||
open(output_file; write=true) do io | ||
# Import symbols required by the bindings | ||
write(io, "import ZeroMQ_jll: libzmq\n") | ||
write(io, "import .lib: zmq_free_fn\n\n") | ||
|
||
for expr in msg_methods | ||
write(io, string(expr), "\n\n") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[general] | ||
library_name = "libzmq" | ||
module_name = "lib" | ||
output_file_path = "../src/bindings.jl" | ||
print_using_CEnum = false | ||
output_ignorelist = ["ZMQ_VERSION"] | ||
prologue_file_path = "./prologue.jl" | ||
|
||
auto_mutability = true | ||
auto_mutability_with_new = false | ||
auto_mutability_includelist = ["zmq_pollitem_t"] | ||
|
||
[codegen] | ||
use_ccall_macro = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import ZeroMQ_jll: libzmq |
Oops, something went wrong.