Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using Mathlink to export arrays

23 views
Skip to first unread message

Amy

unread,
Jun 9, 2006, 2:37:34 AM6/9/06
to
Hi,

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 first tried the following.

if (MLGetShortIntegerArray(...))
{
// do something
}
else if (MLGetIntegerArray(...))
{
// do something else
}
else if (MLGetLongIntegerArray(...))
{
// do something else
}
else if (MLGetFloatArray(...))
{
// do something else
}
else
{
// fail
}

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.

I then tried to change my .tm file so the Pattern only accepted integer
arrays (intending to create a separate function for handling
floating-point arrays), but I could not get that to work either;
neither my integer or floating point arrays were accepted. The relevant
excerpt from my .tm file follows.

:Begin:
:Function: MyFunction
:Pattern: MyFunction[x_?ArrayQ[#, IntegerQ]]
:Arguments: {x}
:ArgumentTypes: {Manual}
:ReturnType: Integer
:End:

Any insights?

- Amy

Jens-Peer Kuska

unread,
Jun 10, 2006, 4:59:52 AM6/10/06
to
Hi,

a) using char, short, int is not your problem
b) when you pass the data not with Manual to your
function
your C-program store it twice. To avoid thiy
you must
pass the data as Manual get the list in the
C-program
copy it to your data and dispose the data in
the link.
c) since Mathematica hold the data always ans int
you should
only pass int to the C-program and check in
your C-code
what data type fits for the range of the input
array
d) for doubles you can setup a second pattern

Regards
Jens

"Amy" <amy.squ...@kitware.com> schrieb im
Newsbeitrag news:e6b4ve$cn5$1...@smc.vnet.net...

ragfield

unread,
Jun 10, 2006, 5:08:00 AM6/10/06
to
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

Amy

unread,
Jun 13, 2006, 1:17:18 AM6/13/06
to

Thanks Rob! That's what I was looking for.
- Amy

0 new messages