Re: Using Mathlink to export arrays
- To: mathgroup at smc.vnet.net
- Subject: [mg67138] Re: Using Mathlink to export arrays
- From: "ragfield" <ragfield at gmail.com>
- Date: Sat, 10 Jun 2006 04:53:43 -0400 (EDT)
- References: <e6b4ve$cn5$1@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
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