Path: news.mathworks.com!not-for-mail
From: <HIDDEN>
Newsgroups: comp.soft-sys.matlab
Subject: Re: mxGetNumberOfDimensions missing ?
Date: Mon, 26 Oct 2009 22:07:01 +0000 (UTC)
Organization: Boeing
Lines: 116
Message-ID: <hc56i5$3p4$1@fred.mathworks.com>
References: <2009102112385016807-spammersgohere@spaminvalid> <hbnv28$c5h$1@fred.mathworks.com> <2009102115045916807-spammersgohere@spaminvalid> <hbo6a4$k5l$1@fred.mathworks.com> <2009102311375416807-spammersgohere@spaminvalid>
Reply-To: <HIDDEN>
NNTP-Posting-Host: webapp-05-blr.mathworks.com
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 8bit
X-Trace: fred.mathworks.com 1256594821 3876 172.30.248.35 (26 Oct 2009 22:07:01 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Mon, 26 Oct 2009 22:07:01 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 756104
Xref: news.mathworks.com comp.soft-sys.matlab:580212


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