Typed args in function that does a ccall

If I have a non-overloaded function such as

loadimage(filename) = @ccall LoadImage(filename::Cstring)::Image

Is there any point in changing it to

loadimage(filename::AbstractString) = @ccall LoadImage(filename::Cstring)::Image

or should I just let ccall deal with it?

Changing it to ::AbstractString would:

  • Document the intended kind of input for the function, which could be helpful to future readers or users
  • Throw a possibly more helpful MethodError if a user passes in something else
  • Allow you to also implement other kinds of image loaders, e.g. loadimage(::IOStream) and let the compiler pick the appropriate one.

If none of those points are important for your current code, then you don’t need to worry about them. You can keep doing loadimage(filename) without any issues.

On the other hand, it would also make your function slightly less general: A user might construct their own type which implements unsafe_convert(::Type{CString}, ...) but which is not a subtype of AbstractString, in which case they would not be able to use your loadimage. However, that’s a pretty odd thing to do, and I would be tempted to blame the user for their weird type definition in that case :slightly_smiling_face:

If you’re looking for an opinion, I would personally prefer loadimage(filename::AbstractString), as it’s more explicit about the function’s intended use without being too restrictive of the input type.

1 Like

Thanks for the fast reply! I was leaning towards changing a lot of these functions and you helped me decide in favor of it.