Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28456 Discussions

Call an Intel Fortran DLL from MATLAB

bjdesa
New Contributor I
883 Views

I need to call a DLL written in IVF V11.x from MATLAB. I dont know how go about solving this problem I was able to solve the problem using the MEX method but I am interested knowing how to call a Fortran compiled Dll in MatLab. For now all I need to is add two numbers and return the output.

[Source2.f90]
real*4 function addnums(val1,val2)
!dec$ attributes dllexport,alias : "addnums" :: addnums
real*4 val1,val2
fortomatreal=val1+val2
end function

How do I generate the addnum.h file from the above code? I dont know c at all.

I found an example of MatLab can I adapt for windows os?

[example.m]
if libisloaded('lib')~=1
if ispc
loadlibrary endecdll.dll endecdll.h alias lib
else % lunix
loadlibrary libendecdll.so endecdll.h alias lib % \\-> for linux
end;
%libfunctions lib libfunctions lib \\-full
%calllib('lib','fortomatint',5,5)
%calllib('lib','fortomatreal',5.4,3.7)
if libisloaded('lib')==1
unloadlibrary lib;
end;

any help would be appreciated

0 Kudos
8 Replies
mecej4
Honored Contributor III
883 Views
These questions are more appropriately asked in a Mathworks/Matlab forum.
0 Kudos
IanH
Honored Contributor II
883 Views

Let me recast your snippet so that it is a little more standard conforming, and works...


[fortran]FUNCTION addnums(val1,val2) BIND(C, NAME='addnums')
!dec$ attributes dllexport :: addnums
  USE ISO_C_BINDING, ONLY: C_FLOAT
  IMPLICIT NONE
  REAL(C_FLOAT), INTENT(IN) :: val1, val2
  REAL(C_FLOAT) :: addnums
  addnums = val1 + val2
END FUNCTION[/fortran]

C_FLOAT is kind 4 with Intel Fortran. Note the arguments val1 and val2 do not have the VALUE attribute - the arguments will be passed by reference.

The equivalent C header for this is:

[cpp]float addnums(float *val1, float *val2);[/cpp]
The * before the parameters in the C declaration means that the arguments are passed by reference (pointers).

You can place that line in a plain text header file (.h) file, and then use that header file as the hfile argument to the matlab loadlibrary function.

Alternatively you can use what is called a prototype function, and pass the handle to the function as the hfile argument. The prototype function returns a matlab structure that describes each call in the library.

[plain]function [methodinfo,structs,enuminfo,ThunkLibName]=prototypes

  % Platform specific.  This is for 32 bit Matlab with 32 bit Intel fortran.
  default_integer = 'int32';
  default_integer_ptr = 'int32ptr';

  ival = {cell(1,1)};
  structs = [];
  enuminfo = [];
  fcnNum = 1;
  fcns=struct('name',ival,'calltype',ival,'LHS',ival,'RHS',ival,'alias',ival);
  ThunkLibName=[];
  
  fcns.name{fcnNum}='addnums'; 
  fcns.calltype{fcnNum}='cdecl';
  fcns.LHS{fcnNum}=['float'];
  fcns.RHS{fcnNum}={'floatPtr', 'floatPtr'};
  fcnNum = fcnNum + 1;  
end[/plain]
To use:

loadlibrary('YourDLLName.dll', @prototypes);

The floatPtr is the equivalent of "pass a float (REAL(4)) by reference".

0 Kudos
bjdesa
New Contributor I
883 Views

[addnums.f90]

FUNCTION addnums(val1,val2) BIND(C, NAME='addnums')

!dec$ attributes dllexport :: addnums

USE ISO_C_BINDING, ONLY: C_FLOAT

IMPLICIT NONE

REAL(C_FLOAT), INTENT(IN) :: val1, val2

REAL(C_FLOAT) :: addnums

addnums = val1 + val2

END FUNCTION

Compiled using Fortran command line for x64

ifort /dll addnums.f90

[addnums.h]

float addnums(float *val1, float *val2);

[prototypes.m]

function [methodinfo,structs,enuminfo,ThunkLibName]=prototypes

% Platform specific. This is for 32 bit Matlab with 32 bit Intel fortran.

default_integer = 'int32';

default_integer_ptr = 'int32ptr';

ival = {cell(1,1)};

structs = [];

enuminfo = [];

fcnNum = 1;

fcns=struct('name',ival,'calltype',ival,'LHS',ival,'RHS',ival,'alias',ival);

ThunkLibName=[];

fcns.name{fcnNum}='addnums';

fcns.calltype{fcnNum}='cdecl';

fcns.LHS{fcnNum}=['float'];

fcns.RHS{fcnNum}={'floatPtr', 'floatPtr'};

fcnNum = fcnNum + 1;

end

What changes are needed to run this on Win XP 64B and Matlab R2011a?

0 Kudos
IanH
Honored Contributor II
883 Views
Quoting bjdesa

What changes are needed to run this on Win XP 64B and Matlab R2011a?


For that specific exanple I don't believe you need to make any changes.

0 Kudos
bjdesa
New Contributor I
883 Views

Interfacing with Fortran

I managed to solve interface with Fortran using the "mexfile method"

The problem is not everyone has a Fortran compiler in my office and they have different MatLab version too.

Therefore I am trying to figure out how to solve it using the loadlibrary method

Computer configuration: OS Win XP 32b and MatLab 2010b 32b

[addnums.f90]

FUNCTION addnums(val1,val2) BIND(C, NAME='addnums')

!dec$ attributes dllexport :: addnums

USE ISO_C_BINDING, ONLY: C_FLOAT

IMPLICIT NONE

REAL(C_FLOAT), INTENT(IN) :: val1, val2

REAL(C_FLOAT) :: addnums

addnums = val1 + val2

END FUNCTION

I compiled using Intel Fortran 11.x

ifort /dll addnums.f90

[addnums.h]

float addnums(float *val1, float *val2);

Now in MatLab the following worked

%loadlibrary('addnums','addnums.h','mfilename','addnums1.m')

The Matlab generated the file 'addnums1.m'

I typed the following and got the following response:

>> loadlibrary('addnums','addnums.h','mfilename','addnums1.m')

>> addnums1(100.0,30.0)

??? Error using ==> addnums1

Too many input arguments.

>> addnums1

ans =

name: {'addnums'}

calltype: {'cdecl'}

LHS: {'single'}

RHS: {{1x2 cell}}

alias: {1x0 cell}

0 Kudos
bjdesa
New Contributor I
883 Views

Interfacing with Fortran

I managed to solve interface with Fortran using the "mexfile method"

The problem is not everyone has a Fortran compiler in my office and they have different MatLab version too.

Therefore I am trying to figure out how to solve it using the loadlibrary method

Computer configuration: OS Win XP 32b and MatLab 2010b 32b

[addnums.f90]

FUNCTION addnums(val1,val2) BIND(C, NAME='addnums')

!dec$ attributes dllexport :: addnums

USE ISO_C_BINDING, ONLY: C_FLOAT

IMPLICIT NONE

REAL(C_FLOAT), INTENT(IN) :: val1, val2

REAL(C_FLOAT) :: addnums

addnums = val1 + val2

END FUNCTION

I compiled using Intel Fortran 11.x

ifort /dll addnums.f90

[addnums.h]

float addnums(float *val1, float *val2);

Now in MatLab the following worked

%loadlibrary('addnums','addnums.h','mfilename','addnums1.m')

The Matlab generated the file 'addnums1.m'

I typed the following and got the following response:

>> loadlibrary('addnums','addnums.h','mfilename','addnums1.m')

>> addnums1(100.0,30.0)

??? Error using ==> addnums1

Too many input arguments.

>> addnums1

ans =

name: {'addnums'}

calltype: {'cdecl'}

LHS: {'single'}

RHS: {{1x2 cell}}

alias: {1x0 cell}

What did I am do wrong?

0 Kudos
IanH
Honored Contributor II
883 Views
The addnums1.m file that you generated is just the equivalent of the prototype function referred to in post #2.

To call the function in the library you use calllib.

calllib('addnums', 'addnums', 1.0, 2.0)

See the matlab help for loadlibrary and calllib for more information.
0 Kudos
bjdesa
New Contributor I
883 Views
[AAA.f90]
SUBROUTINE AAA(a0,Pltout1,Ipltbm1,Npltbm1)
&BIND(C, NAME='AAA')
!dec$ attributes dllexport :: AAA
USE ISO_C_BINDING, ONLY: C_DOUBLE, C_INT
IMPLICIT NONE
REAL(C_DOUBLE), INTENT(IN) :: a0(10)
REAL(C_DOUBLE), INTENT(OUT) :: Pltout1(500,20)
INTEGER(C_INT), INTENT(OUT) :: Ipltbm1, Npltbm1


[AAA.h]
void AAA(double *a0[10], double *nPltout1[500][20], int *Ipltbm1, int *Npltbm1);


>> loadlibrary('AAA','AAA.h')
Warning: The library name case did not match the file name.
The library will be named "AAA".
> In loadlibrary at 174
??? Error using ==> loadlibrary at 477
There was an error loading the library "Z:\MatLab\Project2\AAA.dll"
The specified module could not be found.



Caused by:
Error using ==> loaddefinedlibrary
The specified module could not be found.

What am I doing wrong?
0 Kudos
Reply