Context
I have a custom RPC that works between julia and .NET (discussed in previous posts of mine), though it helped me to understand how this kind of communication works between different softs, it is totally handmade, and therefore not really flexible.
With my RPC, I use named pipes to transport BSON formatted payloads.
Goal
I would like to replace my custom RPC with more standard protocols to ease maintenance and increase reusability of my code. It seems JSONRPC.jl is at the core of the VSCode extension, so I figure this should be a pretty reliable package for that.
However, I have some difficulties to adapt my code.
Questions
- I currently use BSON payloads, because I transport relatively large numeric arrays (wrt the allowed transport delay), so a first question is, is it possible to transport such payloads using JSON RPC ?
- JSONRPC seem to require to use
@dict_readable
and Outboud
on a new type to recognize it as a transportable struct
. Is it really the case I did I misunderstand how to use those ? I would like to declare my types in a scientific package for all base computations in julia (that could be used without transport considerations), then create a glue package to handle all the transport and RPC declarations.
- Is it possible to make JSONRPC to configure a request able to return
Any
to the client ? Or is a request always tied to input and output types ?
Thanks for any advice !
About @dict_readable
and Outbound
.
I came up with several macros of my own to avoid the use of JSONRPC.@dict_readable
since it needs to be called upon type declaration.
So I wrote (my first) three macros
-
@dict_readable T
: Defines the method required to convert a Dict
from a type T
-
@dict_writeable T
: Defines the method required to construct a type T
from a Dict
-
@dict_convert T
: Defines the method required to convert
a Dict
to a type T
I am certain they are not polished and can be much improved (a merge of the three would be nice) but I wanted to log my progress here.
import Base: convert
const NumberOrCharOrString = Union{Number,Char,String}
macro dict_readable(tname)
fex = :($(tname)())
type = eval(:($(tname)))
ex = quote
function $tname(dict::Dict)
end
end
for (fieldname, fieldtype) in zip(fieldnames(type), fieldtypes(type))
sfieldname = string(:($fieldname))
if fieldtype <: Union{T,AbstractArray{T}} where {T<:NumberOrCharOrString}
f = :(dict[$sfieldname])
elseif fieldtype <: AbstractArray{T} where {T}
TT = eltype(fieldtype)
f = :($TT.(dict[$sfieldname]))
else
f = :($fieldtype(dict[$sfieldname]))
end
push!(fex.args, f)
end
push!(ex.args[end].args[2].args, fex)
exx = quote
convert(::Type{$type}, dict::Dict) = $type(dict)
end
return esc(ex)
end
macro dict_convert(tname)
type = eval(:($(tname)))
ex = quote
convert(::Type{$type}, dict::Dict) = $type(dict)
end
return esc(ex)
end
macro dict_writeable(tname)
type = eval(:($(tname)))
fex = :(Dict())
for (fieldname, fieldtype) in zip(fieldnames(type), fieldtypes(type))
sfieldname = string(:($fieldname))
if fieldtype <: Union{T,AbstractArray{T}} where {T<:NumberOrCharOrString}
f = :($sfieldname => type.$fieldname)
elseif fieldtype <: AbstractArray{T} where {T}
f = :($sfieldname => Dict.(type.$fieldname))
else
f = :($sfieldname => Dict(type.$fieldname))
end
push!(fex.args, f)
end
ex = quote
function Dict(type::$tname)
return $fex
end
end
return esc(ex)
end
The problems I have right now seem related to the use of BSON payloads, which require a way to properly convert normal arrays. Currently JSONRPC (unsurprisingly) does not provide this functionality.