How to link I7-compiled-to-C with an external glk library

The I7 docs say one can compile I7 to C and link to an external glk library:

the code below is only the default Glk implementation for an Inform 7-via-C project, and the user can duck out of it by providing an implementation of her own. (Indeed, this could even be cheapglk, as mentioned above.)

I’ve been meaning to try this for most of a year now, and the recent thread on building I7 for use with shared libraries finally inspired me.

And I haven’t really gotten anywhere with it. Has anyone done this? The most directly relevant bits of the docs are (I think):

What should the external C program look like?

2 Likes

I’ve gotten as far as glkterm saying “Please wait…”, then, immediately, “Hit any key to exit”. Which is progress. And though I don’t have it working, I think I know the shape it needs to have.

Fun fact: despite setting a glk implementation, one must also explicitly set a sender and receiver.

1 Like

Hi.

I did some stuff on this.

so;

int main(int argc, char **argv)
{
    i7process_t proc = i7_new_process();

    i7_set_process_receiver(&proc, receiver, 1);
    i7_set_process_sender(&proc, sender);

    run_process_prepare(&proc);

    run_process(&proc);
    if (proc.termination_code == 1)
    {
        fprintf(stderr, "*** Fatal error: halted ***\n");
    }
    return proc.termination_code;
}
static void receiver(int id, wchar_t c, char *style)
{
    switch (id)
    {
    case I7_BODY_TEXT_ID:
        bodyText.add((char)c); // XX wchar
        break;
    case I7_STATUS_TEXT_ID:
        titleText.add((char)c); // XX wchar
        break;
    case I7_BOX_TEXT_ID:
        bodyText.add((char)c); // XX wchar
        break;
    }
}

static char* sender(int count)
{
    static char sender_buffer[256];

    // get your input from UI 
    char* input = getInput();

    strcpy(sender_buffer, input);
    
    return sender_buffer;
}

Oops. a bit more…

i7word_t i7_fn_Main(i7process_t *proc);

static void run_process_prepare(i7process_t *proc)
{
    i7_initialise_memory_and_stack(proc);
    i7_initialise_variables(proc);
    i7_empty_object_tree(proc);
    i7_initialiser(proc);
    i7_initialise_object_tree(proc);
    i7_initialise_miniglk(proc);
}

static int run_process(i7process_t *proc)
{
    int tc = setjmp(proc->execution_env);
    if (tc) {
        if (tc == 2) proc->termination_code = 0; /* terminated mid-stream but benignly */
        else proc->termination_code = tc; /* terminated mid-stream with a fatal error */
    } else {
        i7_fn_Main(proc);
        proc->termination_code = 0; /* terminated because the program completed */
    }
    return proc->termination_code;
}