C string, ACML, etc. for Windows applications

I am using PGF95 version 7.1-3 under Windows. Please look at the following sample code:

integer(4) function WinMain (hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
!DEC$ ATTRIBUTES STDCALL,ALIAS : '_WinMain@16' :: WinMain

   use dfwin
   integer(4) hInstance, hPrevInstance, lpszCmdLine, nCmdShow, iret
   integer(4) imax, n, incx, isamax, k
   real(4) x(10)
   character(len=50) s1

   x = [1, 8, 5, 7, 9, 2, 4, 6, 8, 0]
   n = 10; incx = 1
   imax = isamax(n, x, incx)

   write(s1,'(a,f2.0)') 'Maximum absolute value is: ', x(imax) 
!  s1 = trim(s1)//char(0)
	
   iret = MessageBox(NULL, s1, "Test"C, IOR(MB_ICONHAND,MB_OK))

   WinMain = 0

end

This is a simple windows application which calls BLAS function ISAMAX to compute a index of a real vector element with maximum absolute value. The code can be compiled successfully using the following command:

pgf95 -winapp -fastsse -defaultlib:user32 -defaultlib:shell32 -lblas my_sample.f90

Here are my questions:

(1) Windows API function “MessageBox” requires the string “s1” to be C-type (i.e., has a C null character). However, when I uncomment the line “s1 = trim(s1)//char(0)” in the above code, the compiler issued the following error messages:

my_sample.f90: 
PGF90-S-0075-Subscript, substring, or argument illegal in this context for 'constant' (my_sample.f90: 18)                                                                       
PGF90-S-0146-Expression must be character type (my_sample.f90: 18)

I have no idea why the sentence “s1 = trim(s1)//char(0)” didn’t work here, as the similar code can be compiled in the following console program without any problem:

program test

   integer(4) imax, n, incx, isamax, k
   real(4) x(10)
   character(len=50) s1

   x = [1, 8, 5, 7, 9, 2, 4, 6, 8, 0]
   n = 10; incx = 1
   imax = isamax(n, x, incx)

   write(s1,'(a,f2.0)') 'Maximum absolute value is: ', x(imax) 
   s1 = trim(s1)//char(0)

   write(*,*) s1

end

(2) Assume that I want to use the optimized library ACML instead of BLAS and LAPACK libraries. The following command didn’t work,

pgf95 -winapp -fastsse -defaultlib:user32 -defaultlib:shell32 -lacml my_sample.f90

and the error message was:

my_sample.obj : error LNK2019: unresolved external symbol _ISAMAX@12 referenced in function _winmain@16

After checking from ACML manual, I realized that -Munix option has to be used when the code is linked with ACML. But I got another error when -Munix was added to the command line:

pgf95 -winapp -fastsse -Munix -defaultlib:user32 -defaultlib:shell32 -lacml my_sample.f90

my_sample.f90: 
f90win32main.obj : error LNK2019: unresolved external symbol _winmain referenced in function _WinMain@16

I guess that is because -Munix changed the default calling convention to UNIX type which is not compatible with Windows API libraries. I wondering if there is an alternative way to use ACML for Windows applications.

Thanks.

Hi Jason,

  1. I think the error comes from the use of dfwin. The workaround for now is to use: s1= trim(s1)//’'C

  2. Would remove @… on the!DEC$ ATTRIBUTES line work for you? It should be fine without its size if you compile with -Munix.

Hongyon

It doesn’t work. I got the same error message when changed it to: !DEC$ ATTRIBUTES STDCALL,ALIAS : ‘_WinMain’ :: WinMain".

I suspect the directive STDCALL, which is required for Win32 APIs, doesn’t work with -Munix. On page 122 of PGI User Guide, there is a paragraph says:

“Using the STDCALL calling convention requires the insertion of a compiler directive into the declarations section of any Fortran program unit which calls the STDCALL program unit. This directive has no effect when the -Munix compilation flag is used, meaning you cannot mix UNIX-style argument passing and STDCALL calling conventions within the same file.”

weird …

Hi,

We use STDCALL on win32 by default. Hence there is no need to put the $DEC! in there.

If you want to link with ACML, one way to do it is make an interface to acml(I looked up in acml.h). Here is my example program and it seems to pop up a correct answer.

Compile option(note no -winapp in flags):
PGI$ pgf90 f.f -Mextend -lacml -defaultlib:user32 -defaultlib:shell32

There is a program I copy from you with a little change:

integer(4) function WinMain (hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
use dfwin
interface
integer function isamax (n,x,incx)
!DEC$ ATTRIBUTES C::isamax
!DEC$ ATTRIBUTES REFERENCE::x
integer n,incx
real x(*)
end

end interface

integer(4) hInstance, hPrevInstance, lpszCmdLine, nCmdShow, iret
integer(4) imax, n, incx, k
real(4) x(10)
character(len=50) s1

x = [1, 8, 5, 7, 9, 2, 4, 6, 8, 0]
n = 10; incx = 1
imax = isamax(n, x, incx)

write(s1,’(a,f2.0)’) 'Maximum absolute value is: ‘, x(imax)
s1 = trim(s1)//’'C

iret = MessageBox(NULL, s1, "Test"C, IOR(MB_ICONHAND,MB_OK))

WinMain = 0

end

program testme
integer WinMain
print *, WinMain(1,1,1,1)
end



Hongyon