This works for me:
macro my_ccall(arg)
result = gensym() # Do not conflict with identifiers from the call site even with the brute-force escaping used below
return quote
custom_function_before_ccall()
$result = @ccall $arg
custom_function_after_ccall()
$result # Set return value of quote block
end |> esc
end
custom_function_before_ccall() = println("before")
custom_function_after_ccall() = println("after")
@my_ccall clock()::Int
Note that on the REPL after
is print before the result of clock()
because the REPL does the printing of the return value when the macro is done. This is only an “observer” problem, the execution order is correct.
I had an additional pair of parentheses in the @ccall
, because I forgot, that @ccall
is special syntax and not a usual macro. I am sorry about that.
You had a mix of expr
and arg
which probably did not work.
Please note, that the solutions are totally different, which you will not observe in trivial cases.
In the solution proposed by me, everything is returned by the macro, so the macro is just rewriting code. The function custom_function_*_ccall
are returned by the macro as code (Expr
) and run during runtime. So if you put @my_ccall clock()::Int
into a function, the functions custom_function_*_ccall
are called whenever your function is called.
In your solution, the functions are executed during macro execution time. As your macro only returns a value, custom_function_*_ccall
are not called when your function containing @my_ccall clock()::Int
is called.
When working with macros, you have the chance to sneak something into the early startup phase of your program (depending on when your file is included, imported or used, this can be also quite late). You always need to think whether you really want to do something now or whether you just want to change the code at the macro’s caller to do something later.
So the question really is: What do you want? If this is a one-time initialization, go ahead with your approach executing the functions during macro execution (but keep in mind that macro execution is generally done during module precompilation).
If you just want to save typing and call the functions whenever your function is called, you should switch to the approach suggested by me (or something similar returning the function calls inside an Expr
).