How to enhance Lib to add various functions?

Hello, Crystal community!

I’m trying to create a binding for htslib in Crystal language. HTSlib is a library for reading and writing common file formats in the field of genomics. It has a lot of macro functions, probably to speed up the process. Since these macro functions cannot be wrapped, I need to reimplement them in Crystal.

First, I tried to create a module LibHTS2 that inherits from LibHTS.

Lib LibHTS
end

module LibHTS2 < LibHTS
  extend self
  
  def some_macro_function_c
    # do_something_nice
  end
end

I wanted to add a macro function to LibHTS2 as a class method. However, I found out that Lib cannot be inherited.

Next, I thought about using crystal macros such as method_missing or forward_missing_to.

Lib LibHTS
end

module LibHTS2
  extend self
  
  forward_missing_to(LibHTS)
end

However, this does not seem to work. Moreover, I found an answer on StackOverflow that the Crystal language does not allow method_missing for class methods.

Crystal lang : method_missing for class object?

Well, How can I enhance Lib to add various functions?
Do you have any recommendations?

1 Like

Why do you want to inherit the lib type? That doesn’t make sense to me. A lib type describes bindings to a library. Libraries don’t inherit from each other, so lib bindings don’t inherit as well.

Lib types are supposed to contain only lib definitions. The usual pattern for library bindings in Crystal is to define the raw lib bindings in a lib type and have a separate type (module or class) for exposing a higher-level Crystal API (making use of the lib type’s definitions). That’s where you would implement the macro replacements.

Also note that macros are very different things in C and Crystal. Most likely you don’t need actual macros in Crystal to represent C macros. Especially when C macros are essentially used to define functions in header files as you mentioned. That’s just regular methods in Crystal. You only need macros when you want to generate source code.

I got that Lib cannot be inherited. However, I would like to know whether it is possible to use method_missing or forward_missing_to for class methods. The reason is that I want to define a higher level API as a method of a module.

Perhaps I need to use some introspection to Lib to create a macro like the one described here?

No, I don’t think you can do that.
Might be able to write some macro code to generate method delegators. But you probably shouldn’t just forward to lib functions. This might work fine in some cases, but usually you have to do some additional handling for input/output conversion or error handling for a higher-level API.

1 Like

Thank you very much for your help.
It has become clear to me what I can and cannot do. As you said, I have a feeling that a simple delegate will not work as expected. If I have any more problems, I will ask again. Have a good day.