I am attempting, using 32-bit gfortran in Windows, to call some
Windows API functions. I am having some success, and can for instance
report the current directory. I am using the current mingw binaries,
based on gcc version 4.5.0 (GCC). I compile the program below via:
gfortran -mrtd test4.f90 -otest4.exe
It compiles fine, without warnings.
When I run it, the output is:
Current Dir: C:\temp
0
Current ExeName:
Although GetCurrentDirectory works fine, GetModuleFileName does not;
and I suspect
the reason to lie in the first parameter, for which Windows expects a
4-byte unsigned integer
value of zero or null. How should I pass this unsigned zero ??
I have the same problem tying to use the Windows Sleep function, which
expects
Milliseconds, an unsigned doubleword.
I'd be very grateful to hear of any way to accomplish this from within
Gfortran (ie, not by writing my own C function).
Mark Horridge
!--------------------------------------------------------------
module Win32
use ISO_C_BINDING
implicit none
private
public GetCurrentDirectory
interface
function GetCurrentDirectory(cchBuffer, lpszCurDir)
bind(C,Name='GetCurrentDirectoryA')
use ISO_C_BINDING
implicit NONE
!GCC$ ATTRIBUTES STDCALL :: GetCurrentDirectory
integer(C_LONG) GetCurrentDirectory
integer(C_LONG) cchBuffer
character(kind=C_CHAR) lpszCurDir
end function GetCurrentDirectory
end interface
public GetModuleFileName
interface
function GetModuleFileName(hmod, lpszfnam, cchBuffer)
bind(C,Name='GetModuleFileNameA')
use ISO_C_BINDING
implicit NONE
!GCC$ ATTRIBUTES STDCALL :: GetModuleFileName
integer(C_LONG) GetModuleFileName
integer(C_LONG) hmod
character(kind=C_CHAR) lpszfnam
integer(C_LONG) cchBuffer
end function GetModuleFileName
end interface
end module Win32
program test
use Win32
use ISO_C_BINDING
implicit none
integer(C_LONG) b
character StringA*(255)
b = GetCurrentDirectory(255,StringA)
print *,' Current Dir: '//StringA(1:b)
b = GetModuleFileName(0,StringA,255)
print *,b
print *,' Current ExeName: '//StringA(1:b)
end program test
|
|
0
|
|
|
|
Reply
|
mark
|
11/9/2010 11:14:37 AM |
|
On 11/9/2010 3:14 AM, mark.horridge@buseco.monash.edu.au wrote:
> I am attempting, using 32-bit gfortran in Windows, to call some
> Windows API functions. I am having some success, and can for instance
> report the current directory. I am using the current mingw binaries,
> based on gcc version 4.5.0 (GCC). I compile the program below via:
> gfortran -mrtd test4.f90 -otest4.exe
> It compiles fine, without warnings.
> When I run it, the output is:
> Current Dir: C:\temp
> 0
> Current ExeName:
>
> Although GetCurrentDirectory works fine, GetModuleFileName does not;
> and I suspect
> the reason to lie in the first parameter, for which Windows expects a
> 4-byte unsigned integer
> value of zero or null. How should I pass this unsigned zero ??
> I have the same problem tying to use the Windows Sleep function, which
> expects
> Milliseconds, an unsigned doubleword.
>
> I'd be very grateful to hear of any way to accomplish this from within
> Gfortran (ie, not by writing my own C function).
>
> Mark Horridge
>
> !--------------------------------------------------------------
> module Win32
> use ISO_C_BINDING
> implicit none
> private
>
> public GetCurrentDirectory
> interface
> function GetCurrentDirectory(cchBuffer, lpszCurDir)
> bind(C,Name='GetCurrentDirectoryA')
> use ISO_C_BINDING
> implicit NONE
> !GCC$ ATTRIBUTES STDCALL :: GetCurrentDirectory
> integer(C_LONG) GetCurrentDirectory
> integer(C_LONG) cchBuffer
> character(kind=C_CHAR) lpszCurDir
> end function GetCurrentDirectory
> end interface
>
> public GetModuleFileName
> interface
> function GetModuleFileName(hmod, lpszfnam, cchBuffer)
> bind(C,Name='GetModuleFileNameA')
> use ISO_C_BINDING
> implicit NONE
> !GCC$ ATTRIBUTES STDCALL :: GetModuleFileName
> integer(C_LONG) GetModuleFileName
> integer(C_LONG) hmod
> character(kind=C_CHAR) lpszfnam
> integer(C_LONG) cchBuffer
> end function GetModuleFileName
> end interface
>
> end module Win32
>
> program test
> use Win32
> use ISO_C_BINDING
> implicit none
> integer(C_LONG) b
> character StringA*(255)
> b = GetCurrentDirectory(255,StringA)
> print *,' Current Dir: '//StringA(1:b)
> b = GetModuleFileName(0,StringA,255)
> print *,b
> print *,' Current ExeName: '//StringA(1:b)
> end program test
>
>
I suppose you required value attribute in many of those integer
definitions; without that, you are passing a pointer. This at least
would enable the compiler to complain about mistakes. I read your
character(kind=C_CHAR) definitions as covering only a single character.
--
Tim Prince
|
|
0
|
|
|
|
Reply
|
Tim
|
11/9/2010 1:03:28 PM
|
|
<mark.horridge@buseco.monash.edu.au> wrote in message
news:6d61fd4a-23f6-4c6c-93af-f77da6d48e8d@p20g2000prf.googlegroups.com...
>I am attempting, using 32-bit gfortran in Windows, to call some
> Windows API functions. I am having some success, and can for instance
> report the current directory. I am using the current mingw binaries,
> based on gcc version 4.5.0 (GCC). I compile the program below via:
> gfortran -mrtd test4.f90 -otest4.exe
> It compiles fine, without warnings.
> When I run it, the output is:
> Current Dir: C:\temp
> 0
> Current ExeName:
> Although GetCurrentDirectory works fine, GetModuleFileName does not;
> and I suspect
> the reason to lie in the first parameter, for which Windows expects a
> 4-byte unsigned integer
> value of zero or null. How should I pass this unsigned zero ??
> I have the same problem tying to use the Windows Sleep function, which
> expects
> Milliseconds, an unsigned doubleword.
> I'd be very grateful to hear of any way to accomplish this from within
> Gfortran (ie, not by writing my own C function).
> !--------------------------------------------------------------
> module Win32
> use ISO_C_BINDING
> implicit none
> private
> public GetCurrentDirectory
> interface
> function GetCurrentDirectory(cchBuffer, lpszCurDir)
> bind(C,Name='GetCurrentDirectoryA')
> use ISO_C_BINDING
> implicit NONE
> !GCC$ ATTRIBUTES STDCALL :: GetCurrentDirectory
> integer(C_LONG) GetCurrentDirectory
> integer(C_LONG) cchBuffer
> character(kind=C_CHAR) lpszCurDir
> end function GetCurrentDirectory
> end interface
> public GetModuleFileName
> interface
> function GetModuleFileName(hmod, lpszfnam, cchBuffer)
> bind(C,Name='GetModuleFileNameA')
> use ISO_C_BINDING
> implicit NONE
> !GCC$ ATTRIBUTES STDCALL :: GetModuleFileName
> integer(C_LONG) GetModuleFileName
> integer(C_LONG) hmod
> character(kind=C_CHAR) lpszfnam
> integer(C_LONG) cchBuffer
> end function GetModuleFileName
> end interface
> end module Win32
> program test
> use Win32
> use ISO_C_BINDING
> implicit none
> integer(C_LONG) b
> character StringA*(255)
> b = GetCurrentDirectory(255,StringA)
> print *,' Current Dir: '//StringA(1:b)
> b = GetModuleFileName(0,StringA,255)
> print *,b
> print *,' Current ExeName: '//StringA(1:b)
> end program test
First off, just forget about -mrtd with gfortran. It doesn't work
in any way you might consider sensible. Those !GCC$ ATTRIBUTES STDCALL
Directive Enhanced Compilation statements you put in there do the
right thing already.
Second, if you can, try to make interfacing to Win32 API functions
work in 64-bit Windows then go back and see if what you did works
in 32-bit Windows. 64-bit Windows is so much easier because there
is no issue with STDCALL: there is only one calling convention.
Third, look up the documention for the function you are trying to
interface to in MSDN. Use exactly the names given there; don't
try to be creative or abbreviate or anything. This doesn't have
any effect on whether or not your program works, it just makes
it more self-documenting. But you do have a real problem in
writing the interfaces. The integer arguments are passed by value
according to MSDN, so they should read, for example:
integer(C_LONG), value :: nBufferLength
Also HMODULE is a handle according to MSDN, and handles are
integer(C_INTPTR_T), not integer(C_LONG). Doesn't make a
difference in 32-bit Windows, I know, but if you make the change
as suggested your program will work perfectly in 32-bit gfortran,
64-bit gfortran, and 64-bit ifort. Sorry about 32-bit ifort, Intel
chose to make interfacing to STDCALL procedures not work with
ISO_C_BINDING.
And your string arguments should specify that you are passing
arrays, not single characters by reference. Maybe the way you
are doing works in the compilers you use now, the I dont think
that that is just an accident of implementation, not anything
the standard says.
So fixing just your interface bodies and getting rid of -mrtd, I
get:
C:\gfortran\clf\wintest>type wintest.f90
module Win32
use ISO_C_BINDING
implicit none
private
public GetCurrentDirectory
interface
function GetCurrentDirectory(nBufferLength, lpBuffer) &
bind(C,Name='GetCurrentDirectoryA')
use ISO_C_BINDING
implicit NONE
!GCC$ ATTRIBUTES STDCALL :: GetCurrentDirectory
integer(C_LONG) GetCurrentDirectory
integer(C_LONG),value :: nBufferLength
character(kind=C_CHAR) lpBuffer(*)
end function GetCurrentDirectory
end interface
public GetModuleFileName
interface
function GetModuleFileName(hModule, lpFileName, nSize) &
bind(C,Name='GetModuleFileNameA')
use ISO_C_BINDING
implicit NONE
!GCC$ ATTRIBUTES STDCALL :: GetModuleFileName
integer(C_LONG) GetModuleFileName
integer(C_INTPTR_T), value :: hModule
character(kind=C_CHAR) lpFileName(*)
integer(C_LONG), value :: nSize
end function GetModuleFileName
end interface
end module Win32
program test
use Win32
use ISO_C_BINDING
implicit none
integer(C_LONG) b
character StringA*(255)
b = GetCurrentDirectory(len(StringA),StringA)
print *,' Current Dir: '//StringA(1:b)
b = GetModuleFileName(0_C_INTPTR_T,StringA,len(StringA))
print *,b
print *,' Current ExeName: '//StringA(1:b)
end program test
C:\gfortran\clf\wintest>gfortran wintest.f90 -owintest
C:\gfortran\clf\wintest>wintest
Current Dir: C:\gfortran\clf\wintest
35
Current ExeName: C:\gfortran\clf\wintest\wintest.exe
C:\gfortran\clf\wintest>type wintest.f90
module Win32
use ISO_C_BINDING
implicit none
private
public GetCurrentDirectory
interface
function GetCurrentDirectory(nBufferLength, lpBuffer) &
bind(C,Name='GetCurrentDirectoryA')
use ISO_C_BINDING
implicit NONE
!GCC$ ATTRIBUTES STDCALL :: GetCurrentDirectory
integer(C_LONG) GetCurrentDirectory
integer(C_LONG),value :: nBufferLength
character(kind=C_CHAR) lpBuffer(*)
end function GetCurrentDirectory
end interface
public GetModuleFileName
interface
function GetModuleFileName(hModule, lpFileName, nSize) &
bind(C,Name='GetModuleFileNameA')
use ISO_C_BINDING
implicit NONE
!GCC$ ATTRIBUTES STDCALL :: GetModuleFileName
integer(C_LONG) GetModuleFileName
integer(C_INTPTR_T), value :: hModule
character(kind=C_CHAR) lpFileName(*)
integer(C_LONG), value :: nSize
end function GetModuleFileName
end interface
end module Win32
program test
use Win32
use ISO_C_BINDING
implicit none
integer(C_LONG) b
character StringA*(255)
b = GetCurrentDirectory(len(StringA),StringA)
print *,' Current Dir: '//StringA(1:b)
b = GetModuleFileName(0_C_INTPTR_T,StringA,len(StringA))
print *,b
print *,' Current ExeName: '//StringA(1:b)
end program test
C:\gfortran\clf\wintest>gfortran wintest.f90 -owintest
C:\gfortran\clf\wintest>wintest
Current Dir: C:\gfortran\clf\wintest
35
Current ExeName: C:\gfortran\clf\wintest\wintest.exe
I wish you similar success.
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
|
|
0
|
|
|
|
Reply
|
James
|
11/9/2010 3:56:34 PM
|
|
Thanks very much James van Buskirk,
Of course we had already pored for hours over your previous Gfortran
examples
of how to write a windowed program, and how to create, load and run a
DLL --
but those are hardly beginners examples. Your wintest.f90 is, I think,
the first
example on the internet of how to call some simple windows API
functions from Gfortran.
We have called such windows routines in the past using lf90, lf95,
if32, and if64 -- but these
compilers have various different ways of accomplishing API calls (they
supply import libraries).
We have managed to extend your example to encompass
GlobalMemoryStatus, GetVersionEx, GetWindowsDirectory,
GetCurrentDirectory GetModuleFileName Sleep GetSystemInfo
GetFileAttributes GetCommandLine GetFullPathName and GetLastError
to create 32 and 64-bit exe files which run OK. That program is at:
http://www.monash.edu.au/policy/ftp/gpextra/test9.f90
It gives a compiler warning, and is doubtless sub-optimal -- but gives
a basis to progress further.
CreateProcess may be our next goal.
Thank you again,
Mark Horridge
|
|
0
|
|
|
|
Reply
|
mark
|
11/11/2010 1:21:17 PM
|
|
<mark.horridge@buseco.monash.edu.au> wrote in message
news:041a7967-7669-40f2-b6b7-b71fc774bb5a@u11g2000prn.googlegroups.com...
> We have managed to extend your example to encompass
> GlobalMemoryStatus, GetVersionEx, GetWindowsDirectory,
> GetCurrentDirectory GetModuleFileName Sleep GetSystemInfo
> GetFileAttributes GetCommandLine GetFullPathName and GetLastError
> to create 32 and 64-bit exe files which run OK. That program is at:
> http://www.monash.edu.au/policy/ftp/gpextra/test9.f90
> It gives a compiler warning, and is doubtless sub-optimal -- but gives
> a basis to progress further.
> CreateProcess may be our next goal.
There are a few things I would have changed in your example, but I
haven't gone over the whole thing. You can get rid of the warning
by changing:
character(128) szCSDVersion
to one of:
character(kind=C_CHAR) szCSDVersion*128
character(len=128,kind=C_CHAR) szCSDVersion
character(128,C_CHAR) szCSDVersion
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
|
|
0
|
|
|
|
Reply
|
James
|
11/12/2010 9:02:38 PM
|
|
|
4 Replies
1469 Views
(page loaded in 0.003 seconds)
Similiar Articles: using gfortran to call windows api functions - comp.lang.fortran ...I am attempting, using 32-bit gfortran in Windows, to call some Windows API functions. I am having some success, and can for instance report the cur... Windows API programming with gfortran or g95 - comp.lang.fortran ...... on writing windows api programs using one of the free compilers (g95 or gfortran)? ... callback > function for Windows to call. If you have a main PROGRAM in your Fortran ... trouble with Windows gfortran - comp.lang.fortran... linking to DLL - comp.lang.fortran f95 to windows dll - comp.lang.fortran trouble with Windows gfortran - comp.lang.fortran using gfortran to call windows api functions ... gfortran problem linking to DLL - comp.lang.fortranusing gfortran to call windows api functions - comp.lang.fortran ... gfortran problem linking to DLL - comp.lang.fortran using gfortran to call windows api functions ... f95 to windows dll - comp.lang.fortran... linking to DLL - comp.lang.fortran f95 to windows dll - comp.lang.fortran trouble with Windows gfortran - comp.lang.fortran using gfortran to call windows api functions ... Usage of iso_c_binding - comp.lang.fortranusing gfortran to call windows api functions - comp.lang.fortran ... So fixing just your interface bodies and getting rid of -mrtd, I get: C:\gfortran\clf\wintest>type ... gfortran or ifort? - comp.lang.fortran... some things that gfortran accepts, like a "rand(0)" call inside a pure >function ... great deal, and so use Windows and Fortran ... on Linux - comp.lang.fortran Windows API ... C call C++ fuction and iostream - comp.lang.c++.moderated ...using gfortran to call windows api functions - comp.lang.fortran ... I am attempting, using 32-bit gfortran in Windows, to call some Windows API functions. problem with mixed c and fortran code - comp.lang.fortran ...... Printing from c before fortran call ... This is why my >> fortran functions return an int when I want to use ... for the OS-provided API in both 32-bit and 64-bit Windows ... Calling MATLAB from fortran - comp.soft-sys.matlabHi all, I want to be able to use matlab functions in my fortran code. ... with the program Depends for dll in windows ... I am running WinXP, and I need to call Matlab function ... using gfortran to call windows api functions - comp.lang.fortran ...I am attempting, using 32-bit gfortran in Windows, to call some Windows API functions. I am having some success, and can for instance report the cur... Windows API programming with gfortran or g95 - comp.lang.fortran ...... on writing windows api programs using one of the free compilers (g95 or gfortran)? ... callback > function for Windows to call. If you have a main PROGRAM in your Fortran ... 7/20/2012 3:06:10 PM
|