Thread Subject: mxGetNumberOfDimensions missing ?

Subject: mxGetNumberOfDimensions missing ?

From: Geico Caveman

Date: 21 Oct, 2009 19:38:50

Message: 1 of 16

Mac OSX 10.5.6
Matlab R2009a

gfortran/gcc

Code fragment:

subroutine mexFunction(nlhs, plhs, nrhs, prhs)
  use matlabmex

  implicit none
  
  integer, intent(in) :: nlhs, nrhs
  integer, intent(in), dimension(:), pointer :: prhs
  integer, intent(out), dimension(:), pointer :: plhs

  integer(i4b) :: l,m,n
  integer(i4b), pointer :: n1
  integer(i4b), pointer :: A
  
  if(nrhs /= 2) then
     call mexErrMsgTxt('Function requires four input arguments.');
  end if
  
  A = mxGetData(prhs(1))
  n1 = mxGetDimensions(prhs(1))
   
end subroutine mexFunction


matlabmex.f90 contains:

integer (kind=4) function mxGetData(pm)
     use constants
     integer (kind=4) :: pm
   end function mxGetData

   integer (kind=4) function mxGetDimensions(pm)
     use constants
     integer (kind=4) :: pm
   end function mxGetDimensions

   integer(kind=4) function mxGetNumberOfDimensions(pm)
     use constants
     integer(kind=4) :: pm
   end function mxGetNumberOfDimensions

in the interface block.

Compilation:

/Applications/MATLAB2009a/MATLAB_R2009a.app/bin/mex -maci mexFunction.f90
Undefined symbols:
  "_mxgetdimensions_", referenced from:
      _mexfunction_ in mexFunction.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

    mex: link of ' "mexFunction.mexmaci"' failed.

It can find mxGetData() but not mxGetNumberOfDimensions()

I have checked my matlab documentation to confirm that the function exists.

Subject: mxGetNumberOfDimensions missing ?

From: Geico Caveman

Date: 21 Oct, 2009 20:27:42

Message: 2 of 16

On 2009-10-21 12:38:50 -0700, Geico Caveman
<spammers-go-here@spam.invalid> said:

> Mac OSX 10.5.6
> Matlab R2009a
>
> gfortran/gcc
>
> Code fragment:
>
> subroutine mexFunction(nlhs, plhs, nrhs, prhs)
> use matlabmex
>
> implicit none
> integer, intent(in) :: nlhs, nrhs
> integer, intent(in), dimension(:), pointer :: prhs
> integer, intent(out), dimension(:), pointer :: plhs
>
> integer(i4b) :: l,m,n
> integer(i4b), pointer :: n1
> integer(i4b), pointer :: A
> if(nrhs /= 2) then
> call mexErrMsgTxt('Function requires four input arguments.');
> end if
> A = mxGetData(prhs(1)) n1 = mxGetDimensions(prhs(1))
> end subroutine mexFunction
>
>
> matlabmex.f90 contains:
>
> integer (kind=4) function mxGetData(pm)
> use constants integer (kind=4) :: pm
> end function mxGetData
>
> integer (kind=4) function mxGetDimensions(pm)
> use constants integer (kind=4) :: pm
> end function mxGetDimensions
>
> integer(kind=4) function mxGetNumberOfDimensions(pm)
> use constants
> integer(kind=4) :: pm
> end function mxGetNumberOfDimensions
>
> in the interface block.
>
> Compilation:
>
> /Applications/MATLAB2009a/MATLAB_R2009a.app/bin/mex -maci mexFunction.f90
> Undefined symbols:
> "_mxgetdimensions_", referenced from:
> _mexfunction_ in mexFunction.o
> ld: symbol(s) not found
> collect2: ld returned 1 exit status
>
> mex: link of ' "mexFunction.mexmaci"' failed.
>
> It can find mxGetData() but not mxGetNumberOfDimensions()
>
> I have checked my matlab documentation to confirm that the function exists.

I posted the error and code fragment regarding mxgetdimensions. I have
the same problem with that mex command.

Subject: mxGetNumberOfDimensions missing ?

From: James Tursa

Date: 21 Oct, 2009 21:39:20

Message: 3 of 16

Geico Caveman <spammers-go-here@spam.invalid> wrote in message <2009102112385016807-spammersgohere@spaminvalid>...
> Mac OSX 10.5.6
> Matlab R2009a
>
> gfortran/gcc
>
> Code fragment:
>
> subroutine mexFunction(nlhs, plhs, nrhs, prhs)
> use matlabmex
>
> implicit none
>
> integer, intent(in) :: nlhs, nrhs
> integer, intent(in), dimension(:), pointer :: prhs
> integer, intent(out), dimension(:), pointer :: plhs
>
> integer(i4b) :: l,m,n
> integer(i4b), pointer :: n1
> integer(i4b), pointer :: A
>
> if(nrhs /= 2) then
> call mexErrMsgTxt('Function requires four input arguments.');
> end if
>
> A = mxGetData(prhs(1))
> n1 = mxGetDimensions(prhs(1))
>
> end subroutine mexFunction
>
>
> matlabmex.f90 contains:
>
> integer (kind=4) function mxGetData(pm)
> use constants
> integer (kind=4) :: pm
> end function mxGetData
>
> integer (kind=4) function mxGetDimensions(pm)
> use constants
> integer (kind=4) :: pm
> end function mxGetDimensions
>
> integer(kind=4) function mxGetNumberOfDimensions(pm)
> use constants
> integer(kind=4) :: pm
> end function mxGetNumberOfDimensions
>
> in the interface block.
>
> Compilation:
>
> /Applications/MATLAB2009a/MATLAB_R2009a.app/bin/mex -maci mexFunction.f90
> Undefined symbols:
> "_mxgetdimensions_", referenced from:
> _mexfunction_ in mexFunction.o
> ld: symbol(s) not found
> collect2: ld returned 1 exit status
>
> mex: link of ' "mexFunction.mexmaci"' failed.
>
> It can find mxGetData() but not mxGetNumberOfDimensions()
>
> I have checked my matlab documentation to confirm that the function exists.

Before I make more comments, I would like a few things cleared up. I have never seen this type of mex programming before. It looks like you are attempting to define an interface for the mx functions in a module. And in that module you have functions with the same name as the MATLAB API functions. e.g., let's start with the function mxGetNumberOfDimensions. Is the code you show a function contained in the module, or is it part of an interface definition? What you have shown is not at all clear on this. How is the connection to the actual function in the MATLAB library actually made? And then there is the mxGetDimensions function. The MATLAB API function for this returns an integer*4 on a 32-bit system (used for storing a 32-bit address). You are apparently attempting to get this result, and then return it as an actual Fortran integer pointer type. Is that correct? And then there is the
prhs and plhs definitions that you have. You declared them as pointers to integers. Is that really what you intended? What is the point (no pun intended) of this?

James Tursa

Subject: mxGetNumberOfDimensions missing ?

From: Geico Caveman

Date: 21 Oct, 2009 22:04:59

Message: 4 of 16

On 2009-10-21 14:39:20 -0700, "James Tursa"
<aclassyguy_with_a_k_not_a_c@hotmail.com> said:

> Geico Caveman <spammers-go-here@spam.invalid> wrote in message
> <2009102112385016807-spammersgohere@spaminvalid>...
>> Mac OSX 10.5.6
>> Matlab R2009a
>>
>> gfortran/gcc
>>
>> Code fragment:
>>
>> subroutine mexFunction(nlhs, plhs, nrhs, prhs)
>> use matlabmex
>>
>> implicit none
>>
>> integer, intent(in) :: nlhs, nrhs
>> integer, intent(in), dimension(:), pointer :: prhs
>> integer, intent(out), dimension(:), pointer :: plhs
>>
>> integer(i4b) :: l,m,n
>> integer(i4b), pointer :: n1
>> integer(i4b), pointer :: A
>>
>> if(nrhs /= 2) then
>> call mexErrMsgTxt('Function requires four input arguments.');
>> end if
>>
>> A = mxGetData(prhs(1))
>> n1 = mxGetDimensions(prhs(1))
>>
>> end subroutine mexFunction
>>
>>
>> matlabmex.f90 contains:
>>
>> integer (kind=4) function mxGetData(pm)
>> use constants
>> integer (kind=4) :: pm
>> end function mxGetData
>>
>> integer (kind=4) function mxGetDimensions(pm)
>> use constants
>> integer (kind=4) :: pm
>> end function mxGetDimensions
>>
>> integer(kind=4) function mxGetNumberOfDimensions(pm)
>> use constants
>> integer(kind=4) :: pm
>> end function mxGetNumberOfDimensions
>>
>> in the interface block.
>>
>> Compilation:
>>
>> /Applications/MATLAB2009a/MATLAB_R2009a.app/bin/mex -maci mexFunction.f90
>> Undefined symbols:
>> "_mxgetdimensions_", referenced from:
>> _mexfunction_ in mexFunction.o
>> ld: symbol(s) not found
>> collect2: ld returned 1 exit status
>>
>> mex: link of ' "mexFunction.mexmaci"' failed.
>>
>> It can find mxGetData() but not mxGetNumberOfDimensions()
>>
>> I have checked my matlab documentation to confirm that the function exists.
>
> Before I make more comments, I would like a few things cleared up. I
> have never seen this type of mex programming before. It looks like you
> are attempting to define an interface for the mx functions in a module.
> And in that module you have functions with the same name as the MATLAB
> API functions. e.g., let's start with the function
> mxGetNumberOfDimensions. Is the code you show a function contained in
> the module, or is it part of an interface definition? What you have
> shown is not

This file is a modification of the commonly used f90 mex interface definition:

http://aede.osu.edu/people/roberts.628/papers/research/fmex/toolsandlinks.htm


> at all clear on this. How is the connection to the actual function in
> the MATLAB library actually made? And then there is the mxGetDimensions
> function. The MATLAB API function for this returns an integer*4 on a
> 32-bit system (used for storing a 32-bit address). You are apparently
> attempting to get this result, and then return it as an actual Fortran
> integer pointer type. Is that correct? And then there is the
> prhs and plhs definitions that you have. You declared them as pointers
> to integers. Is that really what you intended? What is the point (no
> pun intended) of this?
>
> James Tursa

The functions mxGetData, or mxGetPr are also defined similarly, and
also return an integer (please consult original post). Since I am
utterly new to mex programming (not new to Fortran (a bit rusty) or
Matlab), I am guessing that the address to the arrays (in these cases)
is returned as an integer that you can use a fortran pointer to point
to.

The point of all this is that function calls from mexFunction.f90 need
to have an interface to call.

The existing mex fortran examples in the documentation, even for R2009a
and R2009b appear to presume that the user is employing fortran 77,
which is obsolescent now in terms of new code development (though there
is plenty of legacy code in f77).

So, it has been a little difficult to get this to work given the
paucity of Mathworks authenticated information.

I used the following example as the starting point of my efforts:

http://www.physik3.gwdg.de/~engster/mex_fortran90.html

I would be glad of any pointers (no pun intended either) to the proper
way of passing a 3D array to fortran, extracting the data and shape
from prhs(1), and creating a 3D array for plhs(1).

Subject: mxGetNumberOfDimensions missing ?

From: James Tursa

Date: 21 Oct, 2009 23:43:01

Message: 5 of 16

Geico Caveman <spammers-go-here@spam.invalid> wrote in message <2009102115045916807-spammersgohere@spaminvalid>...
>
> This file is a modification of the commonly used f90 mex interface definition:
>
> http://aede.osu.edu/people/roberts.628/papers/research/fmex/toolsandlinks.htm
>
> I used the following example as the starting point of my efforts:
>
> http://www.physik3.gwdg.de/~engster/mex_fortran90.html
>
> I would be glad of any pointers (no pun intended either) to the proper
> way of passing a 3D array to fortran, extracting the data and shape
> from prhs(1), and creating a 3D array for plhs(1).

Thanks for the reply ... I will start looking into this.

James Tursa

Subject: mxGetNumberOfDimensions missing ?

From: Geico Caveman

Date: 23 Oct, 2009 18:37:54

Message: 6 of 16

On 2009-10-21 16:43:01 -0700, "James Tursa"
<aclassyguy_with_a_k_not_a_c@hotmail.com> said:

> Geico Caveman <spammers-go-here@spam.invalid> wrote in message
> <2009102115045916807-spammersgohere@spaminvalid>...
>>
>> This file is a modification of the commonly used f90 mex interface definition:
>>
>> http://aede.osu.edu/people/roberts.628/papers/research/fmex/toolsandlinks.htm
>>
>> I used the following example as the starting point of my efforts:
>>
>> http://www.physik3.gwdg.de/~engster/mex_fortran90.html
>>
>> I would be glad of any pointers (no pun intended either) to the proper
>> way of passing a 3D array to fortran, extracting the data and shape
>> from prhs(1), and creating a 3D array for plhs(1).
>
> Thanks for the reply ... I will start looking into this.
>
> James Tursa

Thanks.

I look forward to seeing what you have to say.

Subject: mxGetNumberOfDimensions missing ?

From: James Tursa

Date: 26 Oct, 2009 22:07:01

Message: 7 of 16

Geico Caveman <spammers-go-here@spam.invalid> wrote in message <2009102311375416807-spammersgohere@spaminvalid>...
> On 2009-10-21 16:43:01 -0700, "James Tursa"
> <aclassyguy_with_a_k_not_a_c@hotmail.com> said:
>
> > Geico Caveman <spammers-go-here@spam.invalid> wrote in message
> > <2009102115045916807-spammersgohere@spaminvalid>...
> >>
> >> This file is a modification of the commonly used f90 mex interface definition:
> >>
> >> http://aede.osu.edu/people/roberts.628/papers/research/fmex/toolsandlinks.htm
> >>

I took a look at this code and have a few comments:

The code contains these lines near the top:

integer MatlabPtr = 4 ! 32-bit machines
!integer MatlabPtr = 8 ! 64-bit machines

This leads one to believe that if you only changed the MatlabPtr definition from 4 to 8 you would be OK to use it in a 64-bit system. And indeed you see the effect in these lines:

   ! FUNCTION THAT CREATES AN MXARRAY
   !-----------------------------------------------------------------
   integer (kind=MatlabPtr) function mxCreateDoubleMatrix(m, n, ComplexFlag)
      integer (kind=4) :: m, n, ComplexFlag
   end function mxCreateDoubleMatrix

So here the function either returns an 8-byte integer or a 4-byte integer depending on the MatlabPtr setting. OK, that seems reasonable (although not guaranteed) since you would expect the pointer to be either 4 or 8 bytes in size. But then later on there are these lines:

   ! FUNCTION THAT CREATES STRUCTURE VARIABLE
   !-----------------------------------------------------------------
   integer function mxCreateStructMatrix(m, n, nfields, fieldnames)
      integer(kind=4) :: m, n, nfields
      character (len=*), dimension(nfields) :: fieldnames
   end function mxCreateStructMatrix

mxCreateStructMatrix should return an address pointer same as other routines that create an mxArray variable, and yet here it is only declared as returning an integer(kind=4), not an integer(kind=MatlabPtr). So clearly there is going to be a mismatch here, and almost certainly a program bomb. There are similar problems with other routines.

And then there is code like this:

   ! FUNCTION THAT ADDS A FIELD TO A STRUCTURE VARIABLE
   !-----------------------------------------------------------------
   integer (kind=4) function mxAddField(pm, fieldname)
      integer (kind=4) ::pm
      character (len=*), dimension(:):: fieldname
   end function mxAddField

Here the passed in variable pm should be an integer large enough to hold the address on the system in question, i.e. your MatlabPtr, but it is instead hardcoded to integer(kind=4). Again, on a 64-bit system this will bomb.

So bottom line here is that this code looks OK for putting a simple interface around some of the MATLAB API functions/routines to get the compiler to do some checking for you, but it is *not* set up for 64-bit. I would recommend dumping the MatlabPtr stuff entirely and just go with the MATLAB API method of doing this, namely mwPointer, mwSize, etc. For example, have this at the front end:

#ifndef mwPointer
#define mwPointer integer*4
#endif
#ifndef mwSize
#define mwSize integer*4
#endif

And then in the code use them like this:

   ! FUNCTION THAT CREATES AN MXARRAY
   !-----------------------------------------------------------------
   mwPointer function mxCreateDoubleMatrix(m, n, ComplexFlag)
      mwSize :: m, n
      integer (kind=4) :: ComplexFlag
   end function mxCreateDoubleMatrix

That way, the fintrf.h file will set the size of mwPointer and mwSize automatically and you don't have to worry about it. Since mwPointer and mwSize are not defined for older versions of MATLAB, the #ifndef stuff makes sure that the code will work OK on those versions also. You may also need to add constructs for mwIndex, mwSignedIndex, etc. if you use functions that use those.

Now on to your later attempt to use pointers ...

You can't do what you are trying to do. Using pointers in arguments and function returns requires an explicit interface, and MATLAB does not give you that. For example, look at these lines:

subroutine mexFunction(nlhs, plhs, nrhs, prhs)
  use matlabmex
  implicit none
  integer, intent(in) :: nlhs, nrhs
  integer, intent(in), dimension(:), pointer :: prhs
  integer, intent(out), dimension(:), pointer :: plhs

Here you are telling the compiler that prhs and plhs are assumed shape pointers to integer arrays of rank 1. Well, that will only work if the calling routine (in this case MATLAB itself) has the equivalent interface on its side, and it doesn't. i.e., the compiler will expect that a descriptor will be passed in that contains the target address, size information, etc. You don't get that from the MATLAB side ... all you get is a raw address. So this setup, even if it does compile, is doomed to bomb.

Then you have these lines, apparently intended to fake out the compiler into using the raw addresses returned by mxGetData and mxGetDimensions as pointers:

  integer(i4b) :: l,m,n
  integer(i4b), pointer :: n1
  integer(i4b), pointer :: A
  A = mxGetData(prhs(1))
  n1 = mxGetDimensions(prhs(1))

with the module interface code:

integer (kind=4) function mxGetData(pm)
     use constants
     integer (kind=4) :: pm
   end function mxGetData

   integer (kind=4) function mxGetDimensions(pm)
     use constants
     integer (kind=4) :: pm
   end function mxGetDimensions

Again, use of the pointer with an assumed shape means that there must be an explicit interface involved giving the compiler that information with descriptor passing. The raw mxGetData and mxGetDimensions calls do not do that ... the MATLAB functions only returns a raw address, no descriptor with size information etc. So even if you could get this to compile it would bomb in the general case. So what does the author do at this point? The author avoids the size stuff by declaring the pointers as rank 0, i.e., scalars, even though the actual data are matrices. Apparently this works for him, but quite frankly I am surprised, and I am guessing that it is sheer luck that the compiler assumes that the target address is first in the returned descriptor and thus the pointer assignment works. But after all of that effort, it still didn't buy you much of anything since you still have to manually
pass the sizes down on through the next call to use the pointer as a matrix. So the only thing saved was being able to type A in the calling argument list instead of %val(A). If it is worth it to you to do this, then go ahead.

Is there another way to do this and get a pointer with associated size info attached? I don't think so. What you would be looking for is a function that took a raw address and returned a pointer (descriptor with size info etc). To get the pointer return value to work properly (pointer descriptor with size info etc.) you will require an explicit interface. But to get the raw address stuff to be passed (%val construct) you will need an implicit interface. Since you can't have both, I don't think there is a way to fake out the compiler on this one and get your pointer.

So my advice is to forget the pointer stuff and just be happy with the basic interface provided in the original link you gave me (possibly with the improvements I suggested).

> >> I would be glad of any pointers (no pun intended either) to the proper
> >> way of passing a 3D array to fortran, extracting the data and shape
> >> from prhs(1), and creating a 3D array for plhs(1).

Do you still need help with 3D passing?

James Tursa

Subject: mxGetNumberOfDimensions missing ?

From: James Tursa

Date: 27 Oct, 2009 01:54:03

Message: 8 of 16

"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hc56i5$3p4$1@fred.mathworks.com>...
>
> Is there another way to do this and get a pointer with associated size info attached? I don't think so.

I just had another thought. It might be possible to get the pointer passed back through a COMMON block. I will make some tests and let you know ...

James Tursa

Subject: mxGetNumberOfDimensions missing ?

From: James Tursa

Date: 27 Oct, 2009 18:32:20

Message: 9 of 16

"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hc5jrq$b1n$1@fred.mathworks.com>...
> "James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hc56i5$3p4$1@fred.mathworks.com>...
> >
> > Is there another way to do this and get a pointer with associated size info attached? I don't think so.
>
> I just had another thought. It might be possible to get the pointer passed back through a COMMON block. I will make some tests and let you know ...
>
> James Tursa

It works! This is going to make it a *lot* simpler to use mxArray variables in Fortran code, because you will be able to simply call a function with the mxArray pointer as an input and get back a Fortran pointer with the dimensions already set, so you can use it as a regular Fortran 2D matrix from that point on with *no* data copying involved. I will clean up my code and post an example later this week. Thanks for the original post ... I never would have thought to use pointers this way until I read your post.

James Tursa

Subject: mxGetNumberOfDimensions missing ?

From: Geico Caveman

Date: 30 Oct, 2009 04:40:58

Message: 10 of 16

On 2009-10-27 11:32:20 -0700, "James Tursa"
<aclassyguy_with_a_k_not_a_c@hotmail.com> said:

> "James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in
> message <hc5jrq$b1n$1@fred.mathworks.com>...
>> "James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in
>> message <hc56i5$3p4$1@fred.mathworks.com>...
>>>
>>> Is there another way to do this and get a pointer with associated size
>>> info attached? I don't think so.
>>
>> I just had another thought. It might be possible to get the pointer
>> passed back through a COMMON block. I will make some tests and let you
>> know ...
>>
>> James Tursa
>
> It works! This is going to make it a *lot* simpler to use mxArray
> variables in Fortran code, because you will be able to simply call a
> function with the mxArray pointer as an input and get back a Fortran
> pointer with the dimensions already set, so you can use it as a regular
> Fortran 2D matrix from that point on with *no* data copying involved.
> I will clean up my code and post an example later this week. Thanks for
> the original post ... I never would have thought to use pointers this
> way until I read your post.
>
> James Tursa

Thanks for writing back with such detailed responses. I got busy with a
few other things, and lost track of this.

Let me go over your posts and get back to you this weekend.

Subject: mxGetNumberOfDimensions missing ?

From: Geico Caveman

Date: 5 Nov, 2009 00:35:18

Message: 11 of 16

On 2009-10-27 11:32:20 -0700, "James Tursa"
<aclassyguy_with_a_k_not_a_c@hotmail.com> said:

> "James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in
> message <hc5jrq$b1n$1@fred.mathworks.com>...
>> "James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in
>> message <hc56i5$3p4$1@fred.mathworks.com>...
>>>
>>> Is there another way to do this and get a pointer with associated size
>>> info attached? I don't think so.
>>
>> I just had another thought. It might be possible to get the pointer
>> passed back through a COMMON block. I will make some tests and let you
>> know ...
>>
>> James Tursa
>
> It works! This is going to make it a *lot* simpler to use mxArray
> variables in Fortran code, because you will be able to simply call a
> function with the mxArray pointer as an input and get back a Fortran
> pointer with the dimensions already set, so you can use it as a regular
> Fortran 2D matrix from that point on with *no* data copying involved.
> I will clean up my code and post an example later this week. Thanks for
> the original post ... I never would have thought to use pointers this
> way until I read your post.
>
> James Tursa

I went over your arguments with some interest.

Makes sense. I do have a bigger problem than things not compiling. I am
still mystified by the fact that mxGetData compiles but
mxGetNumberofDimensions (or mxGetDimensions) does not.

Be it so, can you post the working code example with a 3D array use, if
possible, as you promised ?

At this point, the interface appears to be such a mess (when is Matlab
going to make use of the fact that Fortran has had pointers for about
10-12 years now ?), that I am almost tempted to code completely in
Fortran (using gnuplotfortran or dislin for graphic o/p). However, I
prefer matlab's plotting capabilities, so I want to stick with it long
term.

Subject: mxGetNumberOfDimensions missing ?

From: James Tursa

Date: 5 Nov, 2009 01:45:19

Message: 12 of 16

Geico Caveman <spammers-go-here@spam.invalid> wrote in message <2009110417351816807-spammersgohere@spaminvalid>...
>
> I went over your arguments with some interest.
>
> Makes sense. I do have a bigger problem than things not compiling. I am
> still mystified by the fact that mxGetData compiles but
> mxGetNumberofDimensions (or mxGetDimensions) does not.

I can't answer that without seeing your actual interface code. You gave me some links, but those were to other interfaces, not the modified one you are actually using.

> Be it so, can you post the working code example with a 3D array use, if
> possible, as you promised ?
>
> At this point, the interface appears to be such a mess (when is Matlab
> going to make use of the fact that Fortran has had pointers for about
> 10-12 years now ?), that I am almost tempted to code completely in
> Fortran (using gnuplotfortran or dislin for graphic o/p). However, I
> prefer matlab's plotting capabilities, so I want to stick with it long
> term.

Sorry for the delay. As usual, I got carried away with this. I have working code, but it is not polished yet. If you can be patient just a little bit longer, I will try to finish it up in the next couple of days and post by the weekend. Basically, how would you like to be able to do this ...

use MatlabAPImx
     :
mwPointer plhs(*), prhs(*)
real*8, pointer :: Apr(:,:)
     :
Apr => fpGetPr(prhs(1)) ! fpGetPr is a function I wrote
     :

... and then from that point on use Apr as a regular Fortran matrix? e.g., you can use it in whole array computations and assignments, as a matrix in explicit interfaces, do direct array slice indexing with it, etc. etc. etc. Apr is a pointer directly into the pr area of prhs(1) with *no* data copying involved. Very efficient and easy to use. I also have reshape code with *no* data copying involved (the Fortran intrinsic reshape does a data copy). Also, how about this ...

real*8, pointer :: Apr(:,:)
     :
Apr => fpAllocate(4,6) ! fpAllocate is a function I wrote
     :

... and then from that point on use Apr just like above. The difference between this and the Fortran allocate intrinsic is that behind fpAllocate is the mxMalloc function, so the memory is all part of the MATLAB memory manager and will get garbage collected if necessary.

What, specifically, do you want as a 3D example? e.g., with my code you will be able to do this:

use MatlabAPImx
     :
mwPointer plhs(*), prhs(*)
real*8, pointer :: Apr(:,:,:) ! <-- 3D pointer
     :
Apr => fpGetPr3(prhs(1)) ! fpGetPr3 returns a 3D result
     :

Is that what you are looking for?

James Tursa

Subject: mxGetNumberOfDimensions missing ?

From: Geico Caveman

Date: 5 Nov, 2009 04:00:10

Message: 13 of 16

On 2009-11-04 18:45:19 -0700, "James Tursa"
<aclassyguy_with_a_k_not_a_c@hotmail.com> said:

> Geico Caveman <spammers-go-here@spam.invalid> wrote in message
> <2009110417351816807-spammersgohere@spaminvalid>...
>>
>> I went over your arguments with some interest.
>>
>> Makes sense. I do have a bigger problem than things not compiling. I am
>> still mystified by the fact that mxGetData compiles but
>> mxGetNumberofDimensions (or mxGetDimensions) does not.
>
> I can't answer that without seeing your actual interface code. You gave
> me some links, but those were to other interfaces, not the modified one
> you are actually using.

Can I email it to you ?

>
>> Be it so, can you post the working code example with a 3D array use, if
>> possible, as you promised ?
>>
>> At this point, the interface appears to be such a mess (when is Matlab
>> going to make use of the fact that Fortran has had pointers for about
>> 10-12 years now ?), that I am almost tempted to code completely in
>> Fortran (using gnuplotfortran or dislin for graphic o/p). However, I
>> prefer matlab's plotting capabilities, so I want to stick with it long
>> term.
>
> Sorry for the delay. As usual, I got carried away with this. I have
> working code, but it is not polished yet. If you can be patient just a
> little bit longer, I will try to finish it up in the next couple of
> days and post by the weekend. Basically, how would you like to be able
> to do this ...

No problem.

>
> use MatlabAPImx
> :
> mwPointer plhs(*), prhs(*)
> real*8, pointer :: Apr(:,:)
> :
> Apr => fpGetPr(prhs(1)) ! fpGetPr is a function I wrote
> :
>
> ... and then from that point on use Apr as a regular Fortran matrix?
> e.g., you can use it in whole array computations and assignments, as a
> matrix in explicit interfaces, do direct array slice indexing with it,
> etc. etc. etc. Apr is a pointer directly into the pr area of prhs(1)
> with *no* data copying involved. Very efficient and easy to use. I
> also have reshape code with *no* data copying involved (the Fortran
> intrinsic reshape does a data copy). Also, how about this ...
>
> real*8, pointer :: Apr(:,:)
> :
> Apr => fpAllocate(4,6) ! fpAllocate is a function I wrote
> :
>
> ... and then from that point on use Apr just like above. The difference
> between this and the Fortran allocate intrinsic is that behind
> fpAllocate is the mxMalloc function, so the memory is all part of the
> MATLAB memory manager and will get garbage collected if necessary.

Sounds interesting. Maybe you could post this to Matlab's code exchange
once it is ready.

>
> What, specifically, do you want as a 3D example? e.g., with my code
> you will be able to do this:
>
> use MatlabAPImx
> :
> mwPointer plhs(*), prhs(*)
> real*8, pointer :: Apr(:,:,:) ! <-- 3D pointer
> :
> Apr => fpGetPr3(prhs(1)) ! fpGetPr3 returns a 3D result
> :
>
> Is that what you are looking for?

Yes. Basically have three indices. I would want to be able to access
the 3D array pointed to for manipulation in Matlab and Fortran.

I am still a little uncomfortable with all those *4 and *8 as I got
used to the "Use the selected_int_kind() school for maximum code
portability" school. But if it works, it works.

Subject: mxGetNumberOfDimensions missing ?

From: James Tursa

Date: 5 Nov, 2009 09:31:01

Message: 14 of 16

Geico Caveman <spammers-go-here@spam.invalid> wrote in message <2009110421001016807-spammersgohere@spaminvalid>...
> On 2009-11-04 18:45:19 -0700, "James Tursa"
> <aclassyguy_with_a_k_not_a_c@hotmail.com> said:
>
> Can I email it to you ?
>

Yes. Just replace the c with a k in the first word of the e-mail address above.

> Sounds interesting. Maybe you could post this to Matlab's code exchange
> once it is ready.

Will do. I will let you know when it gets posted to the FEX. In the meantime, see below ...

> Yes. Basically have three indices. I would want to be able to access
> the 3D array pointed to for manipulation in Matlab and Fortran.

OK, here is a dramatically pared down example of my code. I clipped out everything except the 3D stuff. It is a simple mex function that performs the calculation sin(A)+7 where A must be a 3D double input. Uses Fortran pointers, accesses the whole arrays through the pointers, accesses the dimensions directly, and allocates memory for a copy and makes a copy and then deallocates it. Enjoy.

James Tursa

!----------------------------------------------------------------------------------------------------------

!-----------------------------------------------------------------------------------
! Programmer: James Tursa
! Function to demonstrate use of Fortran pointers on a 3D double input.
! Performs the calculation B = sin(A) + 7
! Intended for very small dimension sizes because of the printing
!

#include "fintrf.h"

!\
! The following macros are needed for older versions of MATLAB that do not have these
! macros defined in the fintrf.h file.
!/

#ifndef mwSize
#define mwSize integer(4)
#endif

#ifndef mwPointer
#define mwPointer integer(4)
#endif

#ifndef mwIndex
#define mwIndex integer(4)
#endif

!---------------------------------------------------------------------
!---------------------------------------------------------------------
!---------------------------------------------------------------------

      module MatlabAPImex
      
!-----------------------------------------------------
! Interface definitions for MATLAB API mex functions
!-----------------------------------------------------
      
      interface
!-----
      integer(4) function mexPrintf(message)
      character(len=*), intent(in) :: message
      end function mexPrintf
!-----
      end interface

      end module MatlabAPImex

!---------------------------------------------------------------------
!---------------------------------------------------------------------
!---------------------------------------------------------------------

      module MatlabAPImx
      
!-----------------------------------------------------
! Interface definitions for MATLAB API mx functions
!-----------------------------------------------------
      
      interface
!-----
      mwPointer function mxDuplicateArray(pm)
      mwPointer, intent(in) :: pm
      end function mxDuplicateArray
!-----
      subroutine mxFree(ptr)
      mwPointer, intent(in) :: ptr
      end subroutine mxFree
!-----
      mwPointer function mxGetDimensions(pm)
      mwPointer, intent(in) :: pm
      end function mxGetDimensions
!-----
      mwSize function mxGetNumberOfDimensions( mx )
      mwPointer, intent(in) :: mx
      end function mxGetNumberOfDimensions
!-----
      mwPointer function mxGetPr( mx )
      mwPointer, intent(in) :: mx
      end function mxGetPr
!-----
      integer(4) function mxIsDouble( mx )
      mwPointer, intent(in) :: mx
      end function mxIsDouble
!-----
      integer(4) function mxIsSparse(pm)
      mwPointer, intent(in) :: pm
      end function mxIsSparse
!-----
      mwPointer function mxMalloc(n)
      mwSize, intent(in) :: n
      end function mxMalloc
!-----
      end interface

      end module MatlabAPImx

!---------------------------------------------------------------------
!---------------------------------------------------------------------
!---------------------------------------------------------------------

      module MatlabAPIfp
      use MatlabAPImx
      
!-----------------------------------------------------
! Interface definitions for Fortan Pointer functions
!-----------------------------------------------------
      
      interface fpGetPr3
          module procedure fpGetPr3Double
      end interface
      
      interface fpAllocate
          module procedure fpAllocate3Double
      end interface
      
      interface fpDeallocate
          module procedure fpDeallocate3Double
      end interface
      
!-----------------------------------------------------

      contains
      
!-----------------------------------------------------
! Specific Fortran Pointer functions
!-----------------------------------------------------
      
!----------------------------------------------------------------------
      function fpGetPr3Double( mx ) result(fp)
      implicit none
      real(8), pointer :: fp(:,:,:)
!-ARG
      mwPointer, intent(in) :: mx
!-COM
      real(8), pointer :: Apx3(:,:,:)
      common /MatlabAPI_COMA/ Apx3
!-LOC
      mwPointer :: pr
      mwSize :: ndim
      mwSize, pointer :: dims(:)
      mwSize :: dimz(3)
!-----
      ndim = mxGetNumberOfDimensions(mx)
      if( mxIsDouble(mx) == 1 .and. mxIsSparse(mx) == 0 .and. &
     & ndim <= 3 ) then
          pr = mxGetPr( mx )
          dims => fpGetDimensions( mx )
          dimz = 1
          dimz(1:ndim) = dims
          call MatlabAPI_COM_Apx3( %val(pr), dimz )
          fp => Apx3
      else
          nullify( fp )
      endif
      return
      end function fpGetPr3Double
!----------------------------------------------------------------------
      function fpGetDimensions( mx ) result(fp)
      implicit none
      mwSize, pointer :: fp(:)
!-ARG
      mwPointer, intent(in) :: mx
!-COM
      mwSize, pointer :: Dpx(:)
      common /MatlabAPI_COMD/ Dpx
!-LOC
      mwSize :: ndim
      mwPointer :: dims
!-----
      ndim = mxGetNumberOfDimensions( mx )
      dims = mxGetDimensions( mx )
      call MatlabAPI_COM_Dpx(%val(dims), ndim)
      fp => Dpx
      end function fpGetDimensions
!----------------------------------------------------------------------
      function fpAllocate3Double( n1, n2, n3 ) result(fp)
      implicit none
      real(8), pointer :: fp(:,:,:)
!-ARG
      mwSize, intent(in) :: n1, n2, n3
!-COM
      real(8), pointer :: Apx3(:,:,:)
      common /MatlabAPI_COMA/ Apx3
!-LOC
      mwPointer :: mxmemory
!-----
      mxmemory = mxMalloc(n1*n2*n3*8)
      call MatlabAPI_COM_Apx3( %val(mxmemory), (/n1,n2,n3/) )
      fp => Apx3
      return
      end function fpAllocate3Double
!----------------------------------------------------------------------
      subroutine fpDeallocate3Double( fp )
      implicit none
!-ARG
      real(8), pointer, intent(inout) :: fp(:,:,:)
!-LOC
      mwPointer :: mxmemory
!-----
      if( associated(fp) ) then
          mxmemory = %loc(fp)
          call mxFree(mxmemory)
          nullify(fp)
      endif
      return
      end subroutine fpDeallocate3Double

      end module MatlabAPIfp

!---------------------------------------------------------------------
!---------------------------------------------------------------------
!---------------------------------------------------------------------
      
!----------------------------------------------------------------------
! Specific Fortan Helper functions. Not contained in the module because
! we need an implicit interface to get the %val() construct to work
! properly in the calling routine. Passing the appropriate pointer back
! in a COMMON block. Looks awkward, but works beautifully.
!----------------------------------------------------------------------
      subroutine MatlabAPI_COM_Apx3( A, DIMS )
      implicit none
!-ARG
      mwSize, intent(in) :: DIMS(3)
      real(8), target, intent(in) :: A(DIMS(1),DIMS(2),DIMS(3))
!-COM
      real(8), pointer :: Apx3(:,:,:)
      common /MatlabAPI_COMA/ Apx3
!-----
      Apx3 => A
      return
      end subroutine MatlabAPI_COM_Apx3
!----------------------------------------------------------------------
      subroutine MatlabAPI_COM_Dpx(dims, ndim)
      implicit none
!-ARG
      mwSize, intent(in) :: ndim
      mwSize, target, intent(in) :: dims(ndim)
!-COM
      mwSize, pointer :: Dpx(:)
      common /MatlabAPI_COMD/ Dpx
!-----
      Dpx => dims
      return
      end subroutine MatlabAPI_COM_Dpx

!---------------------------------------------------------------------
!---------------------------------------------------------------------
!---------------------------------------------------------------------

      subroutine mexFunction(nlhs, plhs, nrhs, prhs)
      use MatlabAPImex
      use MatlabAPImx
      use MatlabAPIfp
      implicit none
!-ARG
      mwPointer plhs(*), prhs(*)
      integer*4 nlhs, nrhs
!-LOC
      real(8), pointer :: Afp(:,:,:)
      real(8), pointer :: Bfp(:,:,:)
      real(8), pointer :: Cfp(:,:,:)
      mwSize, pointer :: dims(:)
      mwSize dimz(3)
      mwSize i
      integer(4) k
      character(len=100) line
!-----
!\
! Check the input
!/
      if( nrhs /= 1 ) then
          call mexErrMsgTxt("Need one 3D double input")
      endif
      if( nlhs > 1 ) then
          call mexErrMsgTxt("Too many outputs")
      endif
!\
! Get a Fortran pointer to the input variable data area.
!/
      Afp => fpGetPr3(prhs(1))
      if( .not.associated(Afp) ) then
          call mexErrMsgTxt("Input is not 3D double")
      endif
!\
! Generate output variable and get pointer to data area
!/
      plhs(1) = mxDuplicateArray(prhs(1))
      Bfp => fpGetPr3(plhs(1))
      if( .not.associated(Bfp) ) then
          call mexErrMsgTxt("Unable to get pointer to output")
      endif
!\
! Perform an array calculation
!/
      k = mexPrintf("Performing OUT = sin(IN) + 7"//achar(10))
      Bfp = sin(Afp) + 7.d0
!\
! Get the dimensions and print them out
!/
      dims => fpGetDimensions(prhs(1))
      k = mexPrintf("Dimensions are:")
      do i=1,size(dims)-1
          write(line,*) dims(i)
          k = mexPrintf(" "//trim(adjustl(line))//" x")
      enddo
      write(line,*) dims(size(dims))
      k = mexPrintf(" "//trim(adjustl(line))//achar(10))
!\
! Allocate memory to make a copy
!/
      dimz = 1
      dimz(1:size(dims)) = dims
      Cfp => fpAllocate(dimz(1),dimz(2),dimz(3))
      if( .not.associated(Cfp) ) then
          call mexErrMsgTxt("Unable to allocate memory for pointer")
      endif
!\
! Make a copy of the input
!/
      Cfp = Afp
!\
! Print out a couple of the rows to demonstrate array slicing
!/
      k = mexPrintf('Print two rows from copy of input'//achar(10))
      write(line,*) 'Copy(1,:,1) = ',Cfp(1,:,1)
      k = mexPrintf(trim(line)//achar(10))
      if( dimz(1) >= 2 .and. dimz(3) >= 2 ) then
          write(line,*) 'Copy(2,:,2) = ',Cfp(2,:,2)
          k = mexPrintf(trim(line)//achar(10))
      endif
!\
! Free the dynamically allocated memory
!/
      call fpDeallocate(Cfp)
!\
! Done
!/
      end subroutine mexFunction

Subject: mxGetNumberOfDimensions missing ?

From: Geico Caveman

Date: 9 Nov, 2009 21:15:40

Message: 15 of 16

On 2009-11-05 02:31:01 -0700, "James Tursa"
<aclassyguy_with_a_k_not_a_c@hotmail.com> said:

> Geico Caveman <spammers-go-here@spam.invalid> wrote in message
> <2009110421001016807-spammersgohere@spaminvalid>...
>> On 2009-11-04 18:45:19 -0700, "James Tursa"
>> <aclassyguy_with_a_k_not_a_c@hotmail.com> said:
>>
>> Can I email it to you ?
>>
>
> Yes. Just replace the c with a k in the first word of the e-mail address above.

I did send you the email you requested a few days ago.

Thanks for the code. Let me try it out.

Subject: mxGetNumberOfDimensions missing ?

From: James Tursa

Date: 24 Nov, 2009 18:08:21

Message: 16 of 16

"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <hcu60l$n6v$1@fred.mathworks.com>...
>
> > Sounds interesting. Maybe you could post this to Matlab's code exchange
> > once it is ready.
>
> Will do. I will let you know when it gets posted to the FEX.

I just posted the entire package to the FEX. You can find it here:

http://www.mathworks.com/matlabcentral/fileexchange/25934-fortran-95-interface-to-matlab-api-with-extras

Included in it are all of the Fortran pointer routines for directly accessing the pr and pi data areas of an mxArray, getting copies of the data areas directly into an allocated (using mxMalloc) target, creating mxArray variables from a Fortran array in one line, etc. I put in lots of extras, including *all* of my previous Fortran submissions. So this one package has all of my older Fortran submissions for new / replacement API functions as well as all of my new Fortran pointer routines. I think you will find it useful.

There are still several functions that I plan to add, but decided the basics were in shape enough to post what I have so far.

James Tursa

Tags for this Thread

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

rssFeed for this Thread

Contact us at files@mathworks.com