Re: Using Mathlink to export arrays
- To: mathgroup at smc.vnet.net
- Subject: [mg67222] Re: Using Mathlink to export arrays
- From: "Amy" <amy.squillacote at kitware.com>
- Date: Tue, 13 Jun 2006 01:07:12 -0400 (EDT)
- References: <e6b4ve$cn5$1@smc.vnet.net><e6e25g$1t8$1@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
ragfield wrote:
> Amy wrote:
> > I am using Mathlink to move arrays with depth=3 from Mathematica
> > (version 5.2) into a C++ program I am developing. I want to represent
> > the data in my program as fully as possible (i.e., avoid casting to
> > another data type), but I also don't want to use more memory than is
> > necessary to store the data. My program handles arrays of any type of
> > integer data (short integer, integer, and long integer) as well
> > floating-point data (stored as float, not double, in C++). I am trying
> > to figure out how to determine from Mathematica what type (and which
> > MLGet***Array method) I should use based on the data array coming from
> > Mathematica.
>
> ...
>
> > I thought if I passed in floating-point data that the
> > MLGet***IntegerArray methods would return 0 (for failure), but they did
> > not. Instead the MLGetShortIntegerArray method was used, and the
> > floating-point data in the array was cast to a short integer type.
>
>
> MathLink converts types automatically for your convenience (e.g. if an
> Integer is on the link and you call MLGetDouble(), it will convert the
> int to a double). If you want to handle different types yourself you
> need to check the type before calling MLGet*(). This is fairly tricky
> for arrays. There might be other ways to do this, but here is a way
> that works.
>
> If you're expecting an array, verify this with:
>
> if(MLGetRawType(theLink) == MLTK_ARRAY)
> ...
>
> Get the depth and copy the heads onto a separate link:
>
> MLINK theHeadsLink = MLLoopbackOpen(theEnvironment, NULL);
> array_meterp theMeter;
> long theDepth;
> mlapi_token theType;
>
> if(MLGetArrayType0(theLink, theHeadsLink, &theMeter, &theDepth,
> &theType))
> ...
>
> Use the loopback link containing the heads to determine the dimensions:
>
> long* theTotal = 1;
> long* theDimensions = (long*) malloc(sizeof(long) * theDepth);
> for(long i = 0; i < depth; i++)
> {
> long theDim;
> if(MLCheckFunction(theHeadsLink, "List", &theDim))
> {
> theDimensions[i] = dim;
> theTotal *= dim;
> }
> else
> ; //error
> }
>
> Determine what type of data the array contains
>
> switch(MLGetRawType(theLink))
> {
> case MLTK_CUCHAR:
> ...
> break;
> case MLTK_CSHORT:
> ...
> break;
> case MLTK_CINT:
> ...
> break;
> case MLTK_CFLOAT:
> ...
> break;
> default: // etc
> case MLTK_CDOUBLE:
> ...
> break;
> }
>
> Get the actual Data:
>
> float* theData = (float*) malloc(sizeof(float) * theTotal);
> if(MLGetFloatArrayData(theLink, theMeter, theData, theTotal))
> ...
>
> Clean up:
>
> free(theData);
> free(theDimensions);
> MLReleaseGetArrayState0(theLink, theHeadsLink, theMeter);
> MLClose(theHeadsLink);
>
> -Rob
Thanks Rob! That's what I was looking for.
- Amy