Hi Nick.

Thanks again.

I will try the example you gave but it does appear no have a lot more
boiler plate than the original example and I just want to make sure that is
really needed (the least code I have to add for this, the better, as I will
do a complete rewrite yo use the latest Lucy anyway). Here was the original
sample code that worked for me:

    typedef struct MyAnalyzer MyAnalyzer;

    // Transform() is the central Analyzer method.  Check out the
    // documentation in Analyzer.cfh and various implementations; that
    // should give you enough to cargo cult your own version.
    static Inversion*
    S_MyAnalyzer_Transform_IMP(MyAnalyzer *self, Inversion *inversion) {
        return (Inversion*)INCREF(inversion);
    }

    // Create a subclass at runtime.
    static Class*
    S_class_var(void) {
        StackString *class_name = SSTR_WRAP_UTF8("MyAnalyzer", 10);
        Class *klass = Class_fetch_class((String*)class_name);
        if (!klass) {
            klass = Class_singleton((String*)class_name, ANALYZER);
            Class_Override(klass,
                           (cfish_method_t)S_MyAnalyzer_Transform_IMP,
                           LUCY_Analyzer_Transform_OFFSET);
        }
        return klass;
    }

    // Constructor.
    MyAnalyzer*
    MyAnalyzer_new(void) {
        Class *klass = S_class_var();
        return (MyAnalyzer*)Class_Make_Obj(klass);
    }

My main worry with your new example is that there is a considerable amount
of code being written in main and this will all go inside a library.
Because for now I am basically cargo-culting my way around this, I am not
sure what would be the best point to do that initialization. Would doing it
in _new work anyway?

Thanks again.


On Sun, Mar 5, 2017 at 3:32 PM Nick Wellnhofer <[email protected]> wrote:

> On 05/03/2017 17:26, Bruno Albuquerque wrote:
> > So, my question is: Using the trick of overriding specific methods form
> > Analyzer during runtime, is there a way I can also create my own ivars
> and
> > attach it to my overriden analyzer?
>
> Yes, this is possible. See the example code below (based on Lucy 0.6). Note
> that you should implement Equals, Dump, and Load methods if you have an
> Analyzer with ivars. See the Lucy Analyzers for guidance:
>
>      https://github.com/apache/lucy/tree/master/core/Lucy/Analysis
>
> Another option is to write your own Clownfish parcel. Then the Clownfish
> compiler 'cfc' will create all the boilerplate code for you.
>
>      https://lucy.apache.org/docs/c/Clownfish/Docs/WritingClasses.html
>
> > While we are at this, this is all Lucy 0.4.2 (yeah, I know, old) and I am
> > considering moving to the latest version mostly due to the now included
> > golang bindings. I didn't look a lot at the golang bindings yet but will
> it
> > be possible to create a new analyzer in a non-hackish way and entirely in
> > go using it?
>
> Extending Lucy classes from Go isn't supported yet.
>
> Nick
>
>
> #define CFISH_USE_SHORT_NAMES
> #define LUCY_USE_SHORT_NAMES
>
> #include <stdio.h>
>
> #include "Clownfish/Class.h"
> #include "Lucy/Analysis/Analyzer.h"
> #include "Lucy/Analysis/Inversion.h"
>
> typedef struct MyAnalyzer MyAnalyzer;
>
> typedef struct {
>      int i;
>      const char *p;
> } MyAnalyzerIVARS;
>
> Class *MYANALYZER;
> uint32_t MyAnalyzer_IVARS_OFFSET;
>
> static CFISH_INLINE MyAnalyzerIVARS*
> MyAnalyzer_IVARS(MyAnalyzer *self) {
>     char *ptr = (char*)self + MyAnalyzer_IVARS_OFFSET;
>     return (MyAnalyzerIVARS*)ptr;
> }
>
> Analyzer*
> MyAnalyzer_new() {
>      MyAnalyzer *self = (MyAnalyzer*)Class_Make_Obj(MYANALYZER);
>      MyAnalyzerIVARS *const ivars = MyAnalyzer_IVARS(self);
>      ivars->i = 42;
>      ivars->p = "abc";
>      return (Analyzer*)self;
> }
>
> Inversion*
> MyAnalyzer_Transform_IMP(MyAnalyzer *self, Inversion *inversion) {
>      MyAnalyzerIVARS *const ivars = MyAnalyzer_IVARS(self);
>      printf("i=%d\n", ivars->i);
>      return (Inversion*)INCREF(inversion);
> }
>
> int
> main() {
>      lucy_bootstrap_parcel();
>
>      cfish_ClassSpec class_spec = {
>          &MYANALYZER,
>          &ANALYZER,
>          "MyNamespace::MyAnalyzer",
>          sizeof(MyAnalyzerIVARS),
>          &MyAnalyzer_IVARS_OFFSET,
>          0,
>          0,
>          0,
>          0
>      };
>      cfish_ParcelSpec parcel_spec = {
>          &class_spec,
>          NULL,
>          NULL,
>          NULL,
>          1   // Number of classes.
>      };
>
>      Class_bootstrap(&parcel_spec);
>      Class_Override(MYANALYZER, (cfish_method_t)MyAnalyzer_Transform_IMP,
>                     LUCY_Analyzer_Transform_OFFSET);
>
>      Analyzer *analyzer = MyAnalyzer_new();
>      Analyzer_Transform(analyzer, NULL);
>      DECREF(analyzer);
>
>      return 0;
> }
>
>

Reply via email to