Example #1
0
JNIEXPORT jint JNICALL Java_JMatLink_engOpenSingleUseNATIVE 
                               (JNIEnv *env, jobject obj, jstring startCmdS_JNI)
{
    const char *openS     = (*env)->GetStringUTFChars(env, startCmdS_JNI, 0);
    int         retStatus = 0;
    int         engineI;   

    /* find unused entry in engine array */
    engineI = getUnusedEnginePointer();

    if (engineI==0) return 0;  // no more pointers avaiblable

    if (!(engineP[engineI] = engOpenSingleUse(openS, NULL, &retStatus)))
    {
        if (debugB) fprintf(stderr, "\nCan't start MATLAB engine\n");
        (*env)->ReleaseStringUTFChars(env, startCmdS_JNI, openS); // free memory

        delEnginePointer(engineI);
        return 0;
    }

    (*env)->ReleaseStringUTFChars(env, startCmdS_JNI, openS); // free memory

    return engineI;
}
MatLabEngine::MatLabEngine( std::string host ) : _ep( 0 ), _matLabLogFileStreamPtr( 0 ) {
	static std::string startError = "Could not start MatLab Engine.\n"
	 "The most common reasons for a MatLab exception are as follows:\n\n"
	 "   1) MatLab isn't installed on this (the local) machine.  MatLab *MUST*\n"
	 "      be installed on the machine on which MDL2MGA is run.\n"
	 "      IF YOU ARE RUNNING 64-bit WINDOWS XP, YOU MUST INSTALL THE\n"
	 "      32-BIT VERSION OF MATLAB FOR MDL2MGA TO RUN.\n\n"
	 "   2) If MatLab is installed on this machine, it may be that the\n"
	 "      MatLab service is not registered.  To register the MatLab service,\n"
	 "      in a command-prompt type:\n"
	 "        matlab /regserver\n"
	 "      Once you have done this, try running MDL2MGA again.\n\n"
	 "   3) If MatLab is installed on this machine and registered as a server,\n"
	 "      it may be that MatLab is taking a long time to initialize.  So long,\n"
	 "      in fact, that MDL2MGA is timing out before MatLab is able to respond\n"
	 "      to it.  To test this, re-execute MDL2MGA at least 3 more times.\n"
	 "      If MDL2MGA still will not run, please contact your support center.\n\n";

//		int retcode;
//		if (   !(  _ep = engOpenSingleUse( "\0", 0, &retcode )  )   ) {
//			throw Exception( "Cannot start MatLab engine (retcode = " + retcode + ')' );
//		}
//		if (   !(  _ep = engOpen( "\0" )  )   ) {

#ifdef LINUX
	host += "\0";
	if (   !(  _ep = engOpen( host.c_str() )  )   ) {
		throw MatLabUdm::Exception( startError );
	}
#else // Windows
	int retcode;
		if (   !(  _ep = engOpenSingleUse( "\0", 0, &retcode )  )   ) {
			throw std::exception( "Cannot start MatLab engine (retcode = " + retcode + ')' );
		}
#endif
	
	getBuffer()[ BUFSIZE ] = '\0';
	engOutputBuffer( _ep, getBuffer(), BUFSIZE );
}
Example #3
0
void mexFunction(int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[]) {
  char            command[STRLEN];
  char            matlabcmd[STRLEN];
  char            cmd[STRLEN];
  char           *ptr;
  int             poolsize, retval, block, num, i, status;
  #ifndef USE_PTHREADS
          HANDLE TName;
  InitializeCriticalSection(&enginemutex);
  #endif
          
          initFun();
  mexAtExit(exitFun);
  
  /* the first argument is always the command string */
  if (nrhs < 1)
    mexErrMsgTxt("invalid number of input arguments");
  
  if (!mxIsChar(prhs[0]))
    mexErrMsgTxt("invalid input argument #1");
  if (mxGetString(prhs[0], command, STRLEN - 1))
    mexErrMsgTxt("invalid input argument #1");
  
  /* convert to lower case */
  ptr = command;
  while (*ptr) {
    *ptr = tolower(*ptr);
    ptr++;
  }
  
  /****************************************************************************/
  if (strcmp(command, "open") == 0) {
    /* engine open num cmd */
    
    if (nrhs < 2)
      mexErrMsgTxt("Invalid number of input arguments");
    
    if (nrhs > 1) {
      if (!mxIsNumeric(prhs[1]))
        mexErrMsgTxt("Invalid input argument #2, should be numeric");
      poolsize = mxGetScalar(prhs[1]);
    }
    if (nrhs > 2) {
      if (!mxIsChar(prhs[2]))
        mexErrMsgTxt("Invalid input argument #3, should be a string");
      mxGetString(prhs[2], matlabcmd, STRLEN - 1);
    } else {
      sprintf(matlabcmd, "matlab");
    }
    
    if (poolsize < 1)
      mexErrMsgTxt("The number of engines in the pool should be positive");
    
    ENGINEMUTEX_LOCK;
    engine = engOpenSingleUse(NULL, NULL, &retval);	/* returns NULL on failure */
    ENGINEMUTEX_UNLOCK;
    
    if (!engine) {
      exitFun();	/* this cleans up all engines */
      mexErrMsgTxt("failed to open MATLAB engine");
    }
  }
  /****************************************************************************/
  else if (strcmp(command, "close") == 0) {
    /* engine close */
    
    exitFun();
    
    retval = 0;
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    mxGetPr(plhs[0])[0] = retval;
    
  }
  /****************************************************************************/
  else if (strcmp(command, "put") == 0) {
    /* engine put num name val */
    
    if (nrhs != 4)
      mexErrMsgTxt("Exactly four input arguments needed");
    
    if (!mxIsNumeric(prhs[1]))
      mexErrMsgTxt("Argument #2 should be numeric");
    num = mxGetScalar(prhs[1]);
    
    if (num < 1 || num > poolsize)
      mexErrMsgTxt("Invalid engine number");
    
    if (!mxIsChar(prhs[2]))
      mexErrMsgTxt("Argument #3 should be a string");
    
    ENGINEMUTEX_LOCK;
    
    retval = engPutVariable(engine, mxArrayToString(prhs[2]), prhs[3]);
    
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    mxGetPr(plhs[0])[0] = retval;
    
    ENGINEMUTEX_UNLOCK;
  }
  /****************************************************************************/
  else if (strcmp(command, "get") == 0) {
    /* engine get num name */
    
    if (nrhs != 3)
      mexErrMsgTxt("Exactly three input arguments needed");
    
    if (!mxIsNumeric(prhs[1]))
      mexErrMsgTxt("Argument #2 should be numeric");
    
    if (!mxIsChar(prhs[2]))
      mexErrMsgTxt("Argument #3 should be a string");
    
    num = mxGetScalar(prhs[1]);
    
    ENGINEMUTEX_LOCK;
    
    plhs[0] = engGetVariable(engine, mxArrayToString(prhs[2]));
    
    ENGINEMUTEX_UNLOCK;
    
  }
  /****************************************************************************/
  else if (strcmp(command, "isbusy") == 0) {
    /* engine isbusy num */
    
    if (nrhs != 2)
      mexErrMsgTxt("Exactly two input arguments needed");
    
    if (!mxIsNumeric(prhs[1]))
      mexErrMsgTxt("Argument #2 should be numeric");
    num = mxGetScalar(prhs[1]);
    
    ENGINEMUTEX_LOCK;
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    mxGetPr(plhs[0])[0] = 1;
    ENGINEMUTEX_UNLOCK;
  }
  /****************************************************************************/
  else if (strcmp(command, "eval") == 0) {
    /* engine eval num str block */
    
    if (nrhs < 3)
      mexErrMsgTxt("At least three input arguments needed");
    
    if (!mxIsNumeric(prhs[1]))
      mexErrMsgTxt("Argument #2 should be numeric");
    num = mxGetScalar(prhs[1]);
    
    if (!mxIsChar(prhs[2]))
      mexErrMsgTxt("Invalid input argument #3, should be a string");
    mxGetString(prhs[2], cmd, STRLEN - 1);
    
    if (nrhs > 3) {
      if (!mxIsNumeric(prhs[3]))
        mexErrMsgTxt("Invalid input argument #4, should be numeric");
      block = mxGetScalar(prhs[3]);
    } else {
      block = 0;
    }
    
    ENGINEMUTEX_LOCK;
    
    if (!block) {
      
#ifdef USE_PTHREADS
      retval = pthread_create(&(enginepool[num - 1].tid), NULL, (void *) &evalString, (void *) (enginepool + num - 1));
#else
      TName = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) evalString, (void *) (cmd), 0, NULL);
#endif

    } else {
      retval = engEvalString(engine, cmd);
    }
    mexPrintf("Finished executing command, retval = %d\n", retval);
    ENGINEMUTEX_UNLOCK;
    
    WaitForSingleObject(TName, INFINITE);
    
    /* wait for the thread to become busy */
    mexPrintf("Waiting for engine to become busy\n");
    BUSYCOND_WAIT;
    mexPrintf("The engine has become busy\n");
    
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    mxGetPr(plhs[0])[0] = retval;
  }
  /****************************************************************************/
  else if (strcmp(command, "poolsize") == 0) {
    /* engine poolsize */
    
    ENGINEMUTEX_LOCK;
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    mxGetPr(plhs[0])[0] = (engine!=0);
    ENGINEMUTEX_UNLOCK;
  }
  /****************************************************************************/
  else if (strcmp(command, "info") == 0) {
    /* engine info */
    
    ENGINEMUTEX_LOCK;
    mexPrintf("engine = %d\n",   engine);
    ENGINEMUTEX_UNLOCK;
  }
  /****************************************************************************/
  else {
    mexErrMsgTxt("unknown command");
    return;
  }
  
  return;
}
Example #4
0
EXPORT CLASS *init(CALLBACKS *fntable, MODULE *module, int argc, char *argv[])
{
	if (set_callback(fntable)==NULL)
	{
		errno = EINVAL;
		return NULL;
	}

	// open a connection to the Matlab engine
	int status=0;
	static char server[1024];
	if (gl_global_getvar("matlab_server",server,sizeof(server)))
		matlab_server = server;
	if (strcmp(matlab_server,"standalone")==0)
		engine = engOpenSingleUse(NULL,NULL,&status);
	else
		engine = engOpen(matlab_server);
	if (engine==NULL)
	{
		gl_error("unable to start Matlab engine (code %d)",status);
		return NULL;
	}

	// prepare session
	char debug[8];
	if (gl_global_getvar("debug",debug,sizeof(debug)))
		debugmode = (atoi(debug)==1);
	engSetVisible(engine,debugmode?1:0);
	engEvalString(engine,"clear all;");
	char env[1024];
	_snprintf(env,sizeof(env),"NEVER=%g;INVALID=%g;",TOSERIAL(TS_NEVER),TOSERIAL(TS_INVALID));
	engEvalString(engine,env);

	// collect output from Matlab
	engOutputBuffer(engine,output,sizeof(output)); 

	// setup the Matlab module and run the class constructor
	engEvalString(engine,"global passconfig;");
	if (engEvalString(engine,argv[0])!=0)
		gl_error("unable to evaluate function '%s' in Matlab", argv[0]);
	else
		gl_matlab_output();

	// read the pass configuration
	mxArray *pcfg= engGetVariable(engine,"passconfig");
	if (pcfg && mxIsChar(pcfg))
	{
		char passinfo[1024];
		KEYWORD keys[] = {
			{"NOSYNC",PC_NOSYNC,keys+1},
			{"PRETOPDOWN",PC_PRETOPDOWN,keys+2},
			{"BOTTOMUP",PC_BOTTOMUP,keys+3},
			{"POSTTOPDOWN",PC_POSTTOPDOWN,NULL},
		};
		PROPERTY pctype = {0,"passconfig",PT_set,1,PA_PUBLIC,NULL,&passconfig,NULL,keys,NULL};
		set passdata;
		if (mxGetString(pcfg,passinfo,sizeof(passinfo))==0 && callback->convert.string_to_property(&pctype,&passdata,passinfo)>0)
		{
			passconfig = (PASSCONFIG)passdata;
			oclass=gl_register_class(module,argv[0],passconfig);
			if (oclass==NULL)
				gl_error("unable to register '%s' as a class",argv[0]);

			DELEGATEDTYPE *pDelegate = new DELEGATEDTYPE;
			pDelegate->oclass = oclass;
			strncpy(pDelegate->type,"matlab",sizeof(pDelegate->type));
			pDelegate->from_string = object_from_string;
			pDelegate->to_string = object_to_string;
			if (gl_publish_variable(oclass,PT_delegated,pDelegate,"data",0,NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);

		}
		else
			gl_error("passconfig is invalid (expected set of NOSYNC, PRETOPDOWN, BOTTOMUP, and POSTTOPDOWN)", passinfo);
	}
	else
		gl_error("passconfig not specified");

	// read the pass configuration
	mxArray *ans= engGetVariable(engine,"ans");
	if (ans && mxIsStruct(ans))
	{
		defaults = mxDuplicateArray(ans);

		// process the answer
		int nFields = mxGetNumberOfFields(ans), i;
		for (i=0; i<nFields; i++)
		{
			const char *name = mxGetFieldNameByNumber(ans,i);
			mxArray *data = mxGetFieldByNumber(ans,0,i);
			// @todo publish the structure
		}
	}
	else
		gl_error("result of call to matlab::%s did not return a structure", argv[0]);

#ifdef OPTIONAL
	/* TODO: publish global variables (see class_define_map() for details) */
	gl_global_create(char *name, ..., NULL);
	/* TODO: use gl_global_setvar, gl_global_getvar, and gl_global_find for access */
#endif

	/* always return the first class registered */
	return oclass;
}
Example #5
0
EXPORT bool glx_init(glxlink *mod)
{
	gl_verbose("initializing matlab link");
	gl_verbose("PATH=%s", getenv("PATH"));

	// initialize matlab engine
	MATLABLINK *matlab = (MATLABLINK*)mod->get_data();
	matlab->status = 0;
#ifdef WIN32
	if ( matlab->command )
		matlab->engine = engOpen(matlab->command);
	else
		matlab->engine = engOpenSingleUse(NULL,NULL,&matlab->status);
	if ( matlab->engine==NULL )
	{
		gl_error("matlab engine start failed, status code is '%d'", matlab->status);
		return false;
	}
#else
	matlab->engine = engOpen(matlab->command);
	if ( matlab->engine==NULL )
	{
		gl_error("matlab engine start failed");
		return false;
	}
#endif

	// set the output buffer
	if ( matlab->output_buffer!=NULL )
		engOutputBuffer(matlab->engine,matlab->output_buffer,(int)matlab->output_size);

	// setup matlab engine
	engSetVisible(matlab->engine,window_show(matlab));

	gl_debug("matlab link is open");

	// special values needed by matlab
	mxArray *ts_never = mxCreateDoubleScalar((double)(TIMESTAMP)TS_NEVER);
	engPutVariable(matlab->engine,"TS_NEVER",ts_never);
	mxArray *ts_error = mxCreateDoubleScalar((double)(TIMESTAMP)TS_INVALID);
	engPutVariable(matlab->engine,"TS_ERROR",ts_error);
	mxArray *gld_ok = mxCreateDoubleScalar((double)(bool)true);
	engPutVariable(matlab->engine,"GLD_OK",gld_ok);
	mxArray *gld_err = mxCreateDoubleScalar((double)(bool)false);
	engPutVariable(matlab->engine,"GLD_ERROR",gld_err);

	// set the workdir
	if ( strcmp(matlab->workdir,"")!=0 )
	{
#ifdef WIN32
		_mkdir(matlab->workdir);
#else
		mkdir(matlab->workdir,0750);
#endif
		if ( matlab->workdir[0]=='/' )
			matlab_exec(matlab,"cd '%s'", matlab->workdir);
		else
			matlab_exec(matlab,"cd '%s/%s'", getcwd(NULL,0),matlab->workdir);
	}

	// run the initialization command(s)
	if ( matlab->init )
	{
		mxArray *ans = matlab_exec(matlab,"%s",matlab->init);
		if ( ans && mxIsDouble(ans) && (bool)*mxGetPr(ans)==false )
		{
			gl_error("matlab init failed");
			return false;
		}
		else if ( ans && mxIsChar(ans) )
		{
			int buflen = (mxGetM(ans) * mxGetN(ans)) + 1;
			char *string =(char*)malloc(buflen);
			int status_error = mxGetString(ans, string, buflen);
			if (status_error == 0)
			{
				gl_error("'%s'",string);
				return false;
			}
			else
			{			
				gl_error("Did not catch Matlab error");
				return false;
			}
		}
	}

	if ( matlab->rootname!=NULL )
	{
		// build gridlabd data
		mwSize dims[] = {1,1};
		mxArray *gridlabd_struct = mxCreateStructArray(2,dims,0,NULL);

		///////////////////////////////////////////////////////////////////////////
		// build global data
		LINKLIST *item;
		mxArray *global_struct = mxCreateStructArray(2,dims,0,NULL);
		for ( item=mod->get_globals() ; item!=NULL ; item=mod->get_next(item) )
		{
			char *name = mod->get_name(item);
			GLOBALVAR *var = mod->get_globalvar(item);
			mxArray *var_struct = NULL;
			mwIndex var_index;
			if ( var==NULL ) continue;

			// do not map module or structured globals
			if ( strchr(var->prop->name,':')!=NULL )
			{
				// ignore module globals here
			}
			else if ( strchr(var->prop->name,'.')!=NULL )
			{
				char struct_name[256];
				if ( sscanf(var->prop->name,"%[^.]",struct_name)==0 )
				{
					gld_property prop(var);
					var_index = mxAddField(global_struct,prop.get_name());
					var_struct = matlab_create_value(&prop);
					if ( var_struct!=NULL )
					{
						//mod->add_copyto(var->prop->addr,mxGetData(var_struct));
						mxSetFieldByNumber(global_struct,0,var_index,var_struct);
					}
				}
			}
			else // simple data
			{
				gld_property prop(var);
				var_index = mxAddField(global_struct,prop.get_name());
				var_struct = matlab_create_value(&prop);
				if ( var_struct!=NULL )
				{
					//mod->add_copyto(var->prop->addr,mxGetData(var_struct));
					mxSetFieldByNumber(global_struct,0,var_index,var_struct);
				}
			}

			// update export list
			if ( var_struct!=NULL )
			{
				mod->set_addr(item,(void*)var_struct);
				mod->set_index(item,(size_t)var_index);
			}
		}

		// add globals structure to gridlabd structure
		mwIndex gridlabd_index = mxAddField(gridlabd_struct,"global");
		mxSetFieldByNumber(gridlabd_struct,0,gridlabd_index,global_struct);

		///////////////////////////////////////////////////////////////////////////
		// build module data
		dims[0] = dims[1] = 1;
		mxArray *module_struct = mxCreateStructArray(2,dims,0,NULL);

		// add modules
		for ( MODULE *module = callback->module.getfirst() ; module!=NULL ; module=module->next )
		{
			// create module info struct
			mwIndex dims[] = {1,1};
			mxArray *module_data = mxCreateStructArray(2,dims,0,NULL);
			mwIndex module_index = mxAddField(module_struct,module->name);
			mxSetFieldByNumber(module_struct,0,module_index,module_data);
			
			// create version info struct
			const char *version_fields[] = {"major","minor"};
			mxArray *version_data = mxCreateStructArray(2,dims,sizeof(version_fields)/sizeof(version_fields[0]),version_fields);
			mxArray *major_data = mxCreateDoubleScalar((double)module->major);
			mxArray *minor_data = mxCreateDoubleScalar((double)module->minor);
			mxSetFieldByNumber(version_data,0,0,major_data);
			mxSetFieldByNumber(version_data,0,1,minor_data);

			// attach version info to module info
			mwIndex version_index = mxAddField(module_data,"version");
			mxSetFieldByNumber(module_data,0,version_index,version_data);

		}
		gridlabd_index = mxAddField(gridlabd_struct,"module");
		mxSetFieldByNumber(gridlabd_struct,0,gridlabd_index,module_struct);

		///////////////////////////////////////////////////////////////////////////
		// build class data
		dims[0] = dims[1] = 1;
		mxArray *class_struct = mxCreateStructArray(2,dims,0,NULL);
		gridlabd_index = mxAddField(gridlabd_struct,"class");
		mxSetFieldByNumber(gridlabd_struct,0,gridlabd_index,class_struct);
		mwIndex class_id[1024]; // index into class struct
		memset(class_id,0,sizeof(class_id));

		// add classes
		for ( CLASS *oclass = callback->class_getfirst() ; oclass!=NULL ; oclass=oclass->next )
		{
			// count objects in this class
			mwIndex dims[] = {0,1};
			for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) )
			{
				OBJECT *obj = mod->get_object(item);
				if ( obj==NULL || obj->oclass!=oclass ) continue;
				dims[0]++;
			}
			if ( dims[0]==0 ) continue;
			mxArray *runtime_struct = mxCreateStructArray(2,dims,0,NULL);

			// add class 
			mwIndex class_index = mxAddField(class_struct,oclass->name);
			mxSetFieldByNumber(class_struct,0,class_index,runtime_struct);

			// add properties to class
			for ( PROPERTY *prop=oclass->pmap ; prop!=NULL && prop->oclass==oclass ; prop=prop->next )
			{
				mwIndex dims[] = {1,1};
				mxArray *property_struct = mxCreateStructArray(2,dims,0,NULL);
				mwIndex runtime_index = mxAddField(runtime_struct,prop->name);
				mxSetFieldByNumber(runtime_struct,0,runtime_index,property_struct);
			}

			// add objects to class
			for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) )
			{
				OBJECT *obj = mod->get_object(item);
				if ( obj==NULL || obj->oclass!=oclass ) continue;
				mwIndex index = class_id[obj->oclass->id]++;
				
				// add properties to class
				for ( PROPERTY *prop=oclass->pmap ; prop!=NULL && prop->oclass==oclass ; prop=prop->next )
				{
					gld_property p(obj,prop);
					mxArray *data = matlab_create_value(&p);
					mxSetField(runtime_struct,index,prop->name,data);
				}

				// update export list
				mod->set_addr(item,(void*)runtime_struct);
				mod->set_index(item,(size_t)index);
			}
		}

		///////////////////////////////////////////////////////////////////////////
		// build the object data
		dims[0] = 0;
		for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) )
		{
			if ( mod->get_object(item)!=NULL ) dims[0]++;
		}
		dims[1] = 1;
		memset(class_id,0,sizeof(class_id));
		const char *objfields[] = {"name","class","id","parent","rank","clock","valid_to","schedule_skew",
			"latitude","longitude","in","out","rng_state","heartbeat","lock","flags"};
		mxArray *object_struct = mxCreateStructArray(2,dims,sizeof(objfields)/sizeof(objfields[0]),objfields);
		mwIndex n=0;
		for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) )
		{
			OBJECT *obj = mod->get_object(item);
			if ( obj==NULL ) continue;
			class_id[obj->oclass->id]++; // index into class struct

			const char *objname[] = {obj->name&&isdigit(obj->name[0])?NULL:obj->name};
			const char *oclassname[] = {obj->oclass->name};

			if (obj->name) mxSetFieldByNumber(object_struct,n,0,mxCreateCharMatrixFromStrings(mwSize(1),objname));
			mxSetFieldByNumber(object_struct,n,1,mxCreateCharMatrixFromStrings(mwSize(1),oclassname));
			mxSetFieldByNumber(object_struct,n,2,mxCreateDoubleScalar((double)class_id[obj->oclass->id]));
			if (obj->parent) mxSetFieldByNumber(object_struct,n,3,mxCreateDoubleScalar((double)obj->parent->id+1));
			mxSetFieldByNumber(object_struct,n,4,mxCreateDoubleScalar((double)obj->rank));
			mxSetFieldByNumber(object_struct,n,5,mxCreateDoubleScalar((double)obj->clock));
			mxSetFieldByNumber(object_struct,n,6,mxCreateDoubleScalar((double)obj->valid_to));
			mxSetFieldByNumber(object_struct,n,7,mxCreateDoubleScalar((double)obj->schedule_skew));
			if ( isfinite(obj->latitude) ) mxSetFieldByNumber(object_struct,n,8,mxCreateDoubleScalar((double)obj->latitude));
			if ( isfinite(obj->longitude) ) mxSetFieldByNumber(object_struct,n,9,mxCreateDoubleScalar((double)obj->longitude));
			mxSetFieldByNumber(object_struct,n,10,mxCreateDoubleScalar((double)obj->in_svc));
			mxSetFieldByNumber(object_struct,n,11,mxCreateDoubleScalar((double)obj->out_svc));
			mxSetFieldByNumber(object_struct,n,12,mxCreateDoubleScalar((double)obj->rng_state));
			mxSetFieldByNumber(object_struct,n,13,mxCreateDoubleScalar((double)obj->heartbeat));
			mxSetFieldByNumber(object_struct,n,14,mxCreateDoubleScalar((double)obj->lock));
			mxSetFieldByNumber(object_struct,n,15,mxCreateDoubleScalar((double)obj->flags));
			n++;
		}
		gridlabd_index = mxAddField(gridlabd_struct,"object");
		mxSetFieldByNumber(gridlabd_struct,0,gridlabd_index,object_struct);

		///////////////////////////////////////////////////////////////////////////
		// post the gridlabd structure
		matlab->root = gridlabd_struct;
		engPutVariable(matlab->engine,matlab->rootname,matlab->root);
	}

	///////////////////////////////////////////////////////////////////////////
	// build the import/export data
	for ( LINKLIST *item=mod->get_exports() ; item!=NULL ; item=mod->get_next(item) )
	{
		OBJECTPROPERTY *objprop = mod->get_export(item);
		if ( objprop==NULL ) continue;

		// add to published items
		gld_property prop(objprop->obj,objprop->prop);
		item->addr = (mxArray*)matlab_create_value(&prop);
		engPutVariable(matlab->engine,item->name,(mxArray*)item->addr);
	}
	for ( LINKLIST *item=mod->get_imports() ; item!=NULL ; item=mod->get_next(item) )
	{
		OBJECTPROPERTY *objprop = mod->get_import(item);
		if ( objprop==NULL ) continue;

		// check that not already in export list
		LINKLIST *export_item;
		bool found=false;
		for ( export_item=mod->get_exports() ; export_item!=NULL ; export_item=mod->get_next(export_item) )
		{
			OBJECTPROPERTY *other = mod->get_export(item);
			if ( memcmp(objprop,other,sizeof(OBJECTPROPERTY)) )
				found=true;
		}
		if ( !found )
		{
			gld_property prop(objprop->obj,objprop->prop);
			item->addr = (mxArray*)matlab_create_value(&prop);
			engPutVariable(matlab->engine,item->name,(mxArray*)item->addr);
		}
	}

	static int32 matlab_flag = 1;
	gl_global_create("MATLAB",PT_int32,&matlab_flag,PT_ACCESS,PA_REFERENCE,PT_DESCRIPTION,"indicates that MATLAB is available",NULL);
	mod->last_t = gl_globalclock;
	return true;
}