Re: Help With MathLink
- To: mathgroup at smc.vnet.net
- Subject: [mg28956] Re: Help With MathLink
- From: tgayley at wolfram.com (Todd Gayley)
- Date: Wed, 23 May 2001 01:54:25 -0400 (EDT)
- Organization: Wolfram Research, Inc.
- References: <9ea6i5$4sq@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
On 21 May 2001 00:45:57 -0400, "Ersek, Ted R" <ErsekTR at navair.navy.mil> wrote:
>You may remember the RootSearch program I discussed several weeks ago. So
>far I only had a little time to work on it .... I want to do most of the
>work in C and I am having trouble with MathLink. I will make the program
>more elegant once I get it working.
>
>In the Mathematica I define:
>
>In[1]:=
> f = Sin; (* Eventually Rootsearch will automatically define f in a
>privat context. *)
> SampleFunction[x_]:= With[ {y=N[f[x]] },
> If[ MachineNumberQ[y], {x, y, 1.0}, {x, 99.0, 0.0} ]
> ]
>
>(*************************)
>Then I get the following results:
>
>In[2]:= Install[ "rootsearch" ]
>
>Out[2]=
> LinkObject[.\rootsearch.exe,2,2]
>
>
>In[3]:= RootSearch[ Sin[x], {x, 2.0, 3.0}]
>
>Out[3]=
> {{0. , 0. , 0. }, {0. , 0. , 0. }}
>
>I expected the following output instead.
> {{2., 0.909297, 1. },{3., 0.14112, 1. }}
>
>
>Please help me get it working. I can email you the related files if it
>helps.
> Thank you in advance,
> Ted Ersek
>----------------------------------
>
>My MathLink templete is:
>/* ----------------------- */
>:Begin:
>:Function: root_search
>:Pattern: RootSearch[func_,{x_Symbol,x0_Real,x1_Real}]
>
>:Arguments: { x0, x1}
>:ArgumentTypes: { Real, Real }
>:ReturnType: Manual
>:End:
>/* ------------------------- */
>
>My source code is:
>
>/* ------------------------- */
>
>#include "mathlink.h"
>#include "stdlib.h"
>#include "stdio.h"
>
>void sample_function( double x, double *result);
>
>extern void root_search(double x0, double x1);
>
>void root_search(double x0, double x1)
>{
> int total_samples=0;
> int dimensions[2];
> char *heads[2];
> long depth=2;
> double *value_array;
> value_array=(double*)calloc(24,sizeof(double));
>
> sample_function(x0,value_array);
> total_samples++;
>
> sample_function(x1,value_array+3);
> total_samples++;
>
> dimensions[0]=2;
> dimensions[1]=3;
> heads[0]=heads[1]="List";
> MLPutRealArray(stdlink,value_array,dimensions,heads,depth);
> return;
>}
>
>
>void sample_function( double x, double *result )
>{
> long three=3;
>
> MLPutFunction(stdlink,"EvaluatePacket",1);
> MLPutFunction(stdlink,"SampleFunction",1);
> MLPutDouble(stdlink,x);
> MLEndPacket(stdlink);
> MLNextPacket(stdlink);
>
> MLGetRealList(stdlink,&result,&three);
> MLDisownRealList(stdlink,result,three);
> return;
>}
>
>
>
Ted,
The problem is that MLGetRealList does not copy any array data into a buffer for you. Your
code is written with that expectation. MLGetRealList (and the other array-getting
functions) only give you a pointer to a buffer of array data down inside MathLink. You
have to copy that data yourself.
You need to write sample_function like this:
void sample_function( double x, double *result )
{
// No point in any assignment here. MathLink writes into this value; it
// does not read it
long three;
double* arrayData;
MLPutFunction(stdlink,"EvaluatePacket",1);
MLPutFunction(stdlink,"SampleFunction",1);
MLPutDouble(stdlink,x);
MLEndPacket(stdlink);
MLNextPacket(stdlink);
MLGetRealList(stdlink,&arrayData,&three);
memcpy(result, arrayData, three * sizeof(double));
MLDisownRealList(stdlink,arrayData,three);
return;
}
Finally, note that if MLGetRealList actually did copy three doubles into your &result
argument, your program would crash, as you would be blowing away data on the stack, not
writing into the buffer that you had earlier allocated. Aren't pointers fun?
--Todd Gayley
Wolfram Research