gfxgfx
 
Please login or register.

Login with username, password and session length
 
gfx gfx
gfx
1619 Posts in 535 Topics by 781 Members - Latest Member: chekyl43 January 27, 2023, 05:01:36 PM
*
gfx* Home | Help | Search | Login | Register | gfx
gfx
Absoft User Forum  |  Support  |  General  |  passing string to a c dll causes a memory could not be read error
gfx
gfxgfx
 

Author Topic: passing string to a c dll causes a memory could not be read error  (Read 9930 times)

mnflint

  • Newbie
  • *
  • Posts: 3
Hi,

Firstly I am not a fortran programmer normally.  But I have to figure out this problem before our fortran programmer comes back from vacation.  (He doesn't know why this is happening either or what to do about it)

I have a c dll compiled with a microsoft compiler.
I am now trying to use that dll in absoft fortran 9.0.  There are several functions I can use fine with no problems, but one of then, OpenpicFile, is popping up an error message

From my limited perspective the only thing different about this call is that it takes a string argument.  And it seems that there is some issue with reading the all the information it needs to.

I can get other calls, with integer only parameters,  to return the expected values but this one is giving me a problem: 'OpenPicFile'.  When I call this one I get the following popup error:.
    Application Error
    The instruction at "0xfee27da0" referenced memory at "0xfee27da0".  The memory could not be read"".
(of course the memory address ("0xfee27da0") changes every time I run the application)

A couple of weird things.
    1. If I put all the code between a Program / end program the code works without the error.
        It is when I put this into a subroutine and call that subroutine that the error happens. 
        I need to put this in a subroutine
    2. All the functions return an error result, (GetVersion returns the version).  When the result is 1 the function succeeded.  All the functions, including OpenPicFile, return success.  And I can begin to read the file ,(which contains multiple jpgs) and get the bitmapheader info from it.  So it looks like part of the file was read, enough so that I can read the bitmap header.

I guess 1 alternative is to do a mixed language program in c and fortran, but I'm not sure where to begin with that.  It seems like this should be able to work, it's just I need a little help
 
I've included the source to the whole buildable program.  As far as I know my only problem is with the function OpenPicFile, and why it returns a success code but pops up the error window.  This same code works in VB and C# and VS C++.

Thanks for looking.....

complete source code:

program rester
   call testpic22()
end program

subroutine testpic22
   use windows
   !---------------------------------------------------------------
   interface
      stdcall function GetVersion() &                  !_GetVersion@0
         & RESULT (FUNCTION_RESULT)
         integer*4::FUNCTION_RESULT
      end function GetVersion
   end interface
   !---------------------------------------------------------------
   interface;   
      stdcall function OpenPicFile(iFilHan,FileName) &      !Q4_OpenPicFile@8
         & RESULT (FUNCTION_RESULT)
         integer*4 :: iFilHan
         character :: FileName*200
           integer*4 :: FUNCTION_RESULT
      end function
   end interface
   !---------------------------------------------------------------
   interface;
      stdcall function ClosePicFile(iFilHan) &        !Q9_ClosePicFile@4
         & RESULT (FUNCTION_RESULT)
         integer*4 iFilHan
         integer*4::FUNCTION_RESULT
      end function
   end interface
   !---------------------------------------------------------------
   integer*4 iii
   pointer (p,iii)
   pointer (q1,GetVersion)    !_GetVersion@0
   pointer (q4,OpenPicFile)     !_OpenPicFile@8
   pointer (q9,ClosePicFile)    !_ClosePicFile@4
   character RefB200*255
   integer*4 v
   character cname*256
   integer*4 iFilHan

   !-----------------------------------------------------------------
   cname = "gtools.dll"C
   p = LoadLibrary(carg(cname))
   if (p==0) then
     write(*, "(1x,'Error loading lib = ', i9)") p; goto 1000
   else; write(*,"(/1x,'Found lib at p =', i9)") p ; endif
   !-----------------------------------------------------------------
   cname = "_GetVersion@0"C
   q1 = GetProcAddress(p, carg(cname))
   if (q1==0) then
        write(*,"(1x, 'didnt find GetVersion')") ;goto 1000
   else; write(*,"(1x,'Found _GetVersion@0 at q1=', i9)") q1 ; endif
   !-----------------------------------------------------------------
   cname = "_OpenPicFile@8"C
   q4=GetProcAddress(p, carg(cname))
   if (q4==0) then
        write(*,"(1x, 'err OpenPicFile', i9)") ;goto 1000
   else; write(*,"(1x,' OpenPicFile =', i9)") q4 ; endif
   !-----------------------------------------------------------------   
   cname = "_ClosePicFile@4"C
   q9=GetProcAddress(p, carg(cname))
   if (q9==0) then
        write(*,"(1x, 'err closepicfile', i9)") ;goto 1000
   else; write(*,"(1x,' closepicfile =', i9)") q9 ; endif
   !-----------------------------------------------------------------

   v = GetVersion()
   write(*,"(1x,' version : =',i9)") v

   iFilHan=0
   RefB200="D:\\fortranstuff\\project33\\testfile.gfi"C
   v = OpenPicFile(%val(iFilHan),RefB200)
   write(*,"(1x,' open result : =',i9)") v
900 continue
   v= ClosePicFile(iFilHan)     
   write(*,"(1x,' close result : =',i9)") v
   v=freelibrary(p); 
   

1000 continue
end subroutine


Mike Linacre

  • Sr. Member
  • ****
  • Posts: 259
Re: passing string to a c dll causes a memory could not be read error
« Reply #1 on: August 20, 2007, 05:53:17 PM »
Did you put a char(0) at the end of your Fortran character string?
Also function calls are sometimes buggy - it seems that the internal registers aren't always saved and reset correctly, so place the suspect function call in a separate FORTRAN subroutine by itself. You can check if this is the problem by doing a WRITE (*,*) ... just before the suspect function call. This usually prevents the bug.
It is also advisable to be explicit about the calling convention. For instance
Not:  return-value = function (string)
Better: return-value = function (val(loc(trim(string)//char(0))))
« Last Edit: August 20, 2007, 07:33:44 PM by Mike Linacre »

mnflint

  • Newbie
  • *
  • Posts: 3
Re: passing string to a c dll causes a memory could not be read error
« Reply #2 on: August 21, 2007, 12:08:20 PM »
Thanks,

I tried almost what you suggested.  Since I don't know how to pass pointers as subroutine parameters I created a subroutine that takes the minimum code required to run the OpenPicFile function

BTW In C the declaration for OpenPicFile for the filename parameter is the type  LPCSTR

It still seems weird that the C dll is returning a success function and getting the error message, possible like fortran isn't allocating enough memory to open the file, I don't know..just guessing.
And weird that this works if it is not in a subroutine, but just in the main program.

If I do the following
   v = OpenPicFile(val(iFilHan),val(loc(TRIM(RefB200)//CHAR(0))))
I get a compile error:
    The type of the actual argument,  "Cray pointer", does not match "CHARACTER", the type of the dummy argument.
   v = OpenPicFile(%val(iFilHan),%val(%loc(TRIM(RefB200)//CHAR(0))))
I get a compile error:
    Unexpected syntax: "operand" was expected but found "%".

If I do the following
   v = OpenPicFile(%val(iFilHan),%val(%loc(TRIM(RefB200)//CHAR(0))))

So I am using the following
   v = OpenPicFile(%val(iFilHan),TRIM(RefB200)//CHAR(0))

The function still returns a success value but also still brings up the same popup error:

    Application Error
    The instruction at "0xfee27da0" referenced memory at "0xfee27da0".  The memory could not be read"".
BUT now the memory address is now always "0X00000000" every time I run the app.

So now my trimmed down subroutine looks like this

subroutine Openthepicfile()
   use windows
   !---------------------------------------------------------------
   interface;   
      stdcall function OpenPicFile(iFilHan,FileName) &      !Q4_OpenPicFile@8
         & RESULT (FUNCTION_RESULT)
         integer*4 :: iFilHan
         character :: FileName*200
           integer*4 :: FUNCTION_RESULT
      end function
   end interface
   !---------------------------------------------------------------
   integer*4 iii, v, iFilHan
   pointer (p,iii)
   pointer (q4,OpenPicFile)     !_OpenPicFile@8
   character RefB200*256, cname*256
   !-----------------------------------------------------------------
   cname = "geotools.dll"C
   p = LoadLibrary(carg(cname))
   if (p==0) then
     write(*, "(1x,'Error loading geotools = ', i9)") p; goto 1000 ; end if
   !-----------------------------------------------------------------
   cname = "_OpenPicFile@8"C
   q4=GetProcAddress(p, carg(cname))
   if (q4==0) then
        write(*,"(1x, 'err OpenPicFile', i9)") ;goto 1000; end if
   !-----------------------------------------------------------------
   RefB200 = "D:\\fortranstuff\\project33\\8945.gvi"C
   iFilHan = 0
   write (*,*)
   v = OpenPicFile(%val(iFilHan),TRIM(RefB200)//CHAR(0))
!   v = OpenPicFile(val(iFilHan),val(loc(TRIM(RefB200)//CHAR(0))))
!   v = OpenPicFile(%val(iFilHan),%val(%loc(TRIM(RefB200)//CHAR(0))))
   write(*,"(1x, 'my sub res ', i9)") v ;
   
1000 continue
end subroutine




    Application Error
    The instruction at "0xfee27da0" referenced memory at "0xfee27da0".  The memory could not be read"".
(of course the memory address ("0xfee27da0") changes every time I run the application)

Mike Linacre

  • Sr. Member
  • ****
  • Posts: 259
Re: passing string to a c dll causes a memory could not be read error
« Reply #3 on: August 22, 2007, 01:54:55 AM »
Am not familiar with the use of "%" - but then I write in Fortran 77. But you could try your code without the % character.

mnflint

  • Newbie
  • *
  • Posts: 3
Re: passing string to a c dll causes a memory could not be read error
« Reply #4 on: August 23, 2007, 08:52:07 AM »
Since my c dll appears to have opened the file, since it returns a success error code to fortran, could this be a memory issue in fortran causing the error to pop up?  Something like a memory space issue?

Mike Linacre

  • Sr. Member
  • ****
  • Posts: 259
Re: passing string to a c dll causes a memory could not be read error
« Reply #5 on: August 24, 2007, 02:56:00 AM »
The memory error is more likely a mismatch in the calling sequence. The dll could succeed, but because it misread the memory locations, it could have overwritten your FORTRAN memory or tried to write outside the FORTRAN partition. So be exactly explicit about variable lengths, addressing etc. Check into what the dll expects, and make sure you are passing exactly that. This is particularly the case with numerical variable lengths as well as character field lengths and addresses. Does the dll expect a pass by val, pass by reference, pointer to a pointer, or what?

Absoft User Forum  |  Support  |  General  |  passing string to a c dll causes a memory could not be read error
 

gfxgfx
gfx gfx
Powered by MySQL Powered by PHP Valid XHTML 1.0! Valid CSS!