Skip to content

Dynamically loading mods on platforms x-cli-* #522

Closed
@cmidgley

Description

@cmidgley

I would like to be able to dynamically load a mod from inside a platform type of x-cli-* (such as x-cli-win), similar to how microcontrollers can place a mod in the flash xs partition and on reboot have the host and mod available for importing modules. My goal here is to dynamically load a mod from a cloud server, and execute it on both microcontrollers and x-cli-* platforms.

I have gotten the x-cli-win platform working, with my own custom main.c file as follows (all from cut/paste of various code from Moddable):

/*
 * Copyright (c) 2016-2020  Moddable Tech, Inc.
 *
 *   This file is part of the Moddable SDK Runtime.
 * 
 *   The Moddable SDK Runtime is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 * 
 *   The Moddable SDK Runtime is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 * 
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with the Moddable SDK Runtime.  If not, see <http://www.gnu.org/licenses/>.
 *
 */


#include "xsAll.h"
#include "mc.xs.h"

extern txPreparation* xsPreparation;

#define xsFindResult(_THIS,_ID) fxFindResult(the, &_THIS, _ID)

xsBooleanValue fxFindResult(xsMachine* the, xsSlot* slot, xsIndex id)
{
	xsBooleanValue result;
	xsOverflow(-1);
	fxPush(*slot);
	if (fxHasID(the, id)) {
		fxPush(*slot);
		fxGetID(the, id);
		xsResult = *the->stack;
		the->stack++;
		result = 1;
	}
	else
		result = 0;
	return result;
}


int main(int argc, char* argv[])
{
	static txMachine root;
	int error = 0;
	txMachine* machine = &root;
	txPreparation* preparation = xsPreparation();

	c_memset(machine, 0, sizeof(txMachine));
	machine->preparation = preparation;
	machine->keyArray = preparation->keys;
	machine->keyCount = (txID)preparation->keyCount + (txID)preparation->creation.keyCount;
	machine->keyIndex = (txID)preparation->keyCount;
	machine->nameModulo = preparation->nameModulo;
	machine->nameTable = preparation->names;
	machine->symbolModulo = preparation->symbolModulo;
	machine->symbolTable = preparation->symbols;
	
	machine->stack = &preparation->stack[0];
	machine->stackBottom = &preparation->stack[0];
	machine->stackTop = &preparation->stack[preparation->stackCount];
	
	machine->firstHeap = &preparation->heap[0];
	machine->freeHeap = &preparation->heap[preparation->heapCount - 1];
	machine->aliasCount = (txID)preparation->aliasCount;

	machine = fxCloneMachine(&preparation->creation, machine, "tool", NULL);

#ifdef mxInstrument
	fxDescribeInstrumentation(machine, 0, NULL, NULL);
#endif
	xsBeginHost(machine);
	{
		xsVars(2);
#ifdef mxInstrument
		fxSampleInstrumentation(the, 0, NULL);
#endif
		{
			xsTry {
                xsVar(1) = xsAwaitImport("main", XS_IMPORT_DEFAULT);
                if (xsTest(xsVar(1))) {
                    if (xsIsInstanceOf(xsVar(1), xsFunctionPrototype)) {
                        xsCallFunction0(xsVar(1), xsGlobal);
                    }
                    else if (xsFindResult(xsVar(1), xsID_onLaunch)) {
                        xsCallFunction0(xsResult, xsVar(1));
                    }
                }
			}
			xsCatch {
				xsStringValue message = xsToString(xsException);
				fprintf(stderr, "### %s\n", message);
				error = 1;
			}
		}
	}
	xsEndHost(the);
	xsDeleteMachine(machine);
	
	return error;
}

void fxAbort(xsMachine* the, int status) {
	exit(status);
}

I don't understand what the fxCloneMachine call does, but my gut is I need to add some logic following that call, and before I attempt to import the module(s) using xsAwaitImport. My immediate goal is Windows, but I'll eventually need it to operate on Mac and Linux as well.

Any hints on what I should be looking at to do this? I see in the Windows simulator (simulator/win/main.cpp line 698, in fxScreenViewProc handling the WM_LAUNCH_MACHINE message) that it seems to open the file and map the file into memory space (CreateFileMapping and MapViewOfFile). Mac and Linux do something similar, but using mmap instead. After this, it goes into the Simulator fxScreenLaunch method (build/simulator/screen.c line 241) that seems to do some work with xsPreparation, fxMapArchive, and fxPrepareMachine that seem like they may be the trick to pulling all this together?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions