Question: Using a custom wrapper for an external fortran DLL

Dear all, 

I am using a custom wrapper to access the subroutines defined in a fortran DLL. The fortran code is pretty basic: it takes three arguments, a, b, mult. Being a subroutine. it returns the result in 'mult'.

Currently, I can get the result from fortran DLL in my wrapper code. I am not able to get it back in Maple. 

My fortran code is as under: 

      subroutine multiply(a1,b1, mult1) bind (C, name="multiply")

        use iso_c_binding
        implicit none

        real (c_double), intent(in), VALUE :: a1
        real (c_double), intent(in), VALUE :: b1
        real (c_double), intent(out) :: mult1

        mult1 = a1*b1

        return
      end subroutine multiply

I tried using this subroutine from a regular C file and it works, so this code works the way it should. 

Now the custom wrapper that I use (obtained by editing the auto-generated wrapper)

/* MWRAP_multiply Wrapper
   Generated automatically by Maple 2015.0.
   Do not edit this file. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mplshlib.h>

#include <maplec.h>

typedef void *MaplePointer;
static MKernelVector mapleKernelVec;
static ALGEB *args;

/* main - MWRAP_multiply */
//ALGEB M_DECL MWRAP_multiply( MKernelVector kv,
//	void (M_DECL *fn) ( FLOAT64 a1, FLOAT64 a2, FLOAT64 a3 ),
//	ALGEB fn_args )

ALGEB mmultiply(MKernelVector kv, ALGEB fn_args)

{
    FLOAT64 a1;
    FLOAT64 a2;
    FLOAT64 a3;

    int i;
    mapleKernelVec = kv;
    args = (ALGEB*) fn_args;

    if( MapleNumArgs(mapleKernelVec,(ALGEB)args) != 3 )
        MapleRaiseError(mapleKernelVec,"Incorrect number of arguments");

     /* float[8] */
    a1 = MapleToFloat64(mapleKernelVec,args[1]);

    /* float[8] */
    a2 = MapleToFloat64(mapleKernelVec,args[2]);

    /* float[8] */
    a3 = MapleToFloat64(mapleKernelVec,args[3]);

    //(*fn)(a1, a2, a3);
    multiply(a1, a2, &a3);

    MaplePrintf(kv, "Output from multiply %f", a3);

    return( ToMapleNULL(mapleKernelVec) );
}

Since the fortran subroutine calls are call by reference, we need to pass the address of a3, (&a3). Then I compile this to create the DLL using: 

gcc -shared -fPIC -o libmmultiply.so mult.f90 mwrap_multiply.c -I /opt/maple2015/extern/include/ -L /opt/maple2015/bin.X86_64_LINUX/ -lmaplec -lgfortran

And then copying the resulting DLL (libmmultiply.so) to the Maple/bin folder. 

Then in Maple : 

mult := define_external("mmultiply",MAPLE,LIB="libmmultiply.so");

mult1 := 0.01;

mult(2., 3., mult1);
### Printed in Maple: Output from multiply 6.000000

mult1;
### Still 0.01 (we want this to be 6.0)

So, it can be seen that the fortran subroutine is successfully executed, so we get 6.0 as the output. However, this does'nt get assigned to 'mult1. The reason for this, I feel, is that the reference to the original variable 'mult1' in Maple is lost in the wrapper, and so the resulting value doesn't update 'mult1'. 

How can I get the resulting value back in Maple ? I want to get this in 'mult1', as most fortran legacy codes use the subroutine method of returning results by updating the arguments. 

Thanks 

Chintan Pathak 

Please Wait...