Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

can not call Win Api function

mavlik
Beginner
1,629 Views

I useDigital Visual Fortran 6.0 (and Compaq Visual Fortran 6.5)
I write a win32 application using win api functions. Some functions calls successfully,
but function LoadImage doesn't want to be called. I have a error:
Error: This name does not have a type, and must have an explicit type.[LOADIMAGE]
Bitmap = LoadImage(0,&
-------------^
It seems to me that this function didn't declare in Fortran's libraries.
Iwrite the prototype of function below:
The LoadImage function loads an icon, cursor, or bitmap.

HANDLE LoadImage(

HINSTANCE hinst, // handle of the instance that contains the image
LPCTSTR lpszName,// name or identifier of image
UINT uType,// type of image
int cxDesired,// desired width
int cyDesired,// desired height
UINT fuLoad// load flags
);

And my part of code that I try to compile
integer(2) Bitmap
LoadImage("img.bmp"C,0,0)
Bitmap = LoadImage(0, &
"img.bmp"C, &
IMAGE_BITMAP, &
0, &
0, &
IOR(LR_DEFAULTSIZE, LR_LOADFROMFILE) &
)
May be it needs to call this function orsomehow stdcall it...

I need help.

0 Kudos
31 Replies
Paul_Curtis
Valued Contributor I
1,161 Views
Add this explicit interface to your code:
[cpp]INTERFACE
    INTEGER*4 FUNCTION LoadImage(hinst, lpszName, uType, cxDesired, &
         cyDesired, fuLoad)
        !DEC$ ATTRIBUTES DEFAULT :: LoadImage
        !DEC$ ATTRIBUTES STDCALL, ALIAS : '_LoadImageA@24' :: LoadImage
        !DEC$ ATTRIBUTES REFERENCE :: lpszName
        INTEGER hinst
        CHARACTER*(*) lpszName
        INTEGER uType
        INTEGER cxDesired
        INTEGER cyDesired
        INTEGER fuLoad
    END FUNCTION LoadImage
END INTERFACE
[/cpp]

0 Kudos
Steven_L_Intel1
Employee
1,161 Views
You need to add:

USE DFWIN

just after the PROGRAM or SUBROUTINE statement where this is called.
0 Kudos
mavlik
Beginner
1,161 Views
Thank you, Paul Curtis !

I make project as Fortran Windows Application ----> A simple Document Interface(SDI)
and try to modify it. The structure of project consist of 4 functions:
WinMain()
MainWndProc()
CenterWindow()
AboutDlgProc()
A window is created in function WinMain() and all my winapi function calls I make in it ( in WinMain() ).
The Workspace include some header file such as .fi, fd and .h.
If I correctly understood .fi file is a interface because in it is written structures like you have write to me.
And in code section (in MainWndProc) there is a reference to this file: include 'opp.fi'
I' ve added the declaration of function LoadImage that you gave in header file 'opp.fi' and than try to compile..
And have a error.
Error: Not a valid attribute for the DEC$ ATTRIBUTES directive. [DEFAULT]
!DEC$ ATTRIBUTES DEFAULT :: LoadImage
------------------------------^

ToSteve Lionel : DFWIN is already linked up to project but erro is still appear
0 Kudos
Steven_L_Intel1
Employee
1,161 Views
DVF 6.0 doesn't support DEFAULT. Just add the USE DFWIN and don't put in your own interface block. DFWIN gives you declarations of thousands of Win32 API routines, types and constants.
0 Kudos
mavlik
Beginner
1,161 Views
DVF 6.0 doesn't support DEFAULT. Just add the USE DFWIN and don't put in your own interface block. DFWIN gives you declarations of thousands of Win32 API routines, types and constants.

Above I added to my post that DFWIN is already connected.
There are4 files: DFWIN.MOD, DFWIN.AVX, DFWIN.C, DFWIN.F90, but they don't include the declaration of function LoadImage
and many other functions. The function MessageBoxA is calles normally but I can not find where it is declarated....
So I think that it is necessary to declare this function manually how it made Mr. Paul Curtis.
But error is still exist...(

P.S. Hm..may be Compaq Visual Fortran 6.5 support directive DEFAULT ?

[Added]:
I try to declarate how it adviced Paul Curtis but keep only 2 lines of directive (other code is same)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_LoadImageA@24' :: LoadImage
!DEC$ ATTRIBUTES REFERENCE :: lpszName

Also in my code there is function CreateDIBSection that is not declarated too...
Now I try to declarate it ....
I have also question: what means the line
!DEC$ ATTRIBUTES REFERENCE :: lpszName
In helps written that it presents with dummy argument....
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,161 Views
Quoting - mavlik

Above I added to my post that DFWIN is already connected.
There are4 files: DFWIN.MOD, DFWIN.AVX, DFWIN.C, DFWIN.F90, but they don't include the declaration of function LoadImage
and many other functions. The function MessageBoxA is calles normally but I can not find where it is declarated....
So I think that it is necessary to declare this function manually how it made Mr. Paul Curtis.
But error is still exist...(

P.S. Hm..may be Compaq Visual Fortran 6.5 support directive DEFAULT ?

[Added]:
I try to declarate how it adviced Paul Curtis but keep only 2 lines of directive (other code is same)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_LoadImageA@24' :: LoadImage
!DEC$ ATTRIBUTES REFERENCE :: lpszName

Also in my code there is function CreateDIBSection that is not declarated too...
Now I try to declarate it ....
I have also question: what means the line
!DEC$ ATTRIBUTES REFERENCE :: lpszName
In helps written that it presents with dummy argument....

I (still) remember the issues surrounding LoadImage, but the oldest version I have is 6.6 so I can't verify what's the situation in 6.0, because changes were introduced gradually. Here we go:


  • There is unrelated DFLIB (QuickWin) function LOADIMAGE. If you USE both DFLIB and DFWIN, you would get a name conflict. For that reason, Win32 LoadImage might be absent from your DFWIN, or renamed to something else. Do a "Find in Files" in "C:PROGRAM FILESMICROSOFT VISUAL STUDIODF98INCLUDE" for the symbol to see which forms are there, and if "yours" (aliased "LoadImageA") is declared at all.
  • In any case, Paul's interface block is correct, modulo DEFAULT attribute, which was added in CVF 6.5. You don't need it unless you use some relatively exotic changes in project's calling convention.
REFERENCE attribute in this particular case specifies that the string lengh is not passed (as common to all C/winapi functions)... but the semantics are arcane. Don't ask what REFERENCE means in other cases :).




0 Kudos
Les_Neilson
Valued Contributor II
1,161 Views
Quoting - mavlik
Above I added to my post that DFWIN is already connected.

I'm not sure what you mean by "connected".
It would help if you showed more of your code but as Steve said, you should have something like :

SUBROUTINE MYSUB
USE DFWIN
IMPLICIT NONE
...
... your call to LOADIMAGE
...

if you do this you don't need your own INTERFACE block for LOADIMAGE

Also just for information .fi doesn't mean an "interface file" although it may contain interface blocks. It is just an include file (whichcould be named .ins or .inc or whatever) The statement include .fi merely means that the contents of that file are inserted (or included) into the source file at that point.

Les

Les
0 Kudos
mavlik
Beginner
1,161 Views
Quoting - Les Neilson
I'm not sure what you mean by "connected".
It would help if you showed more of your code but as Steve said, you should have something like

I mean that the module is declared in project: use DFWIN.

Quoting - Les Neilson
REFERENCE attribute in this particular case specifies that the string lengh is not passed (as common to all C/winapi functions)... but the semantics are arcane. Don't ask what REFERENCE means in other cases :).

I don't understan why it is unnecessary t pass the string length in this function..I didn't meet such doing in c++ or delphi (pascal).

And also I have a question about Mr. Paul Curtis's function declaration: CHARACTER*(*) lpszName

Is it pointer to string?

0 Kudos
TimP
Honored Contributor III
1,161 Views
Quoting - mavlik

Quoting - Les Neilson
REFERENCE attribute in this particular case specifies that the string lengh is not passed (as common to all C/winapi functions)... but the semantics are arcane. Don't ask what REFERENCE means in other cases :).

I don't understan why it is unnecessary t pass the string length in this function..I didn't meet such doing in c++ or delphi (pascal).

And also I have a question about Mr. Paul Curtis's function declaration: CHARACTER*(*) lpszName

Is it pointer to string?

I think you mean you would like to avoid a string length parameter.
If you want to view a CHARACTER string as simply a C pointer to string, without the added string length parameter or the non-standard REFERENCE attribute, you need a compiler which supports f2003 USE iso_c_binding. Such compilers were first widely available about a year ago. In any case, it won't become a null-terminated C string unless you append the null character explicitly, or use another non-standard option, and I don't have any confidence personally in using CVF for such purposes. Without the null terminator or the length parameter, the length isn't available to the callee.
0 Kudos
Paul_Curtis
Valued Contributor I
1,161 Views
LoadImage as shown in my post above works fine in all versions from CVF6.1 through IVF11.0.074. The filename argument is a null-terminated string containing the full path to the file. Eg,

fname = 'c:somepathsomefile.bmp'//CHAR(0)

hbitmap = LoadImage (ghInstance, fname, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,161 Views
I don't understan why it is unnecessary t pass the string length in this function..I didn't meet such doing in c++ or delphi (pascal).

And also I have a question about Mr. Paul Curtis's function declaration: CHARACTER*(*) lpszName

Is it pointer to string?


Fortran passes string length as a [hidden] argument by default. That's because Fortran strings are fixed-length buffers, rather than �-terminated ones; in this way, the original length is known all along the call stack (so you cannot make a buffer overflow notorious for C). However, since C functions don't use or want this length, !DEC$ATTRIBUTES REFERENCE "deletes" this argument.

CHARACTER(*) lpszName is a string argument; you may think of it as a "pointer to string" if you like, because it`s interoperable with C char*. The second asterisk indicates that the length is passed (inferred from the actual argument length) -- however, REFERENCE attribute will suppress that.
0 Kudos
mavlik
Beginner
1,161 Views
I express my thanks for all answers but have another problem with my project.
I put the declaration of function CreateDIBSection into .fi file in my project.

INTERFACE
INTEGER*4 FUNCTION
CreateDIBSection(HDC, pbmi, iUsage, ppvBits, &
hSection, dwOffset)
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_CreateDIBSection@24' :: CreateDIBSection
INTEGER HDC
TYPE (T_BITMAPINFO) pbmi
INTEGER(4) iUsage
POINTER ppvBits
INTEGER*4 hSection
INTEGER*4 dwOffset
END FUNCTION CreateDIBSection
END INTERFACE

But during linking apppears a error:
Error: This derived type name has not been declared. [T_BITMAPINFO]
TYPE (T_BITMAPINFO) pbmi
----------------^

This type is declarated in unit DFWINTY, but the file "opp.fi" is processed the first whereas
declaration of DFWIN is in main function (WinMain).
Also I have noticed that file "user32.lib" contain function _LoadImageA@24 but
file user32.f90 don't contain. And it is a very strange thing.
I want to extract this library and get .obj file which I think is possible to use in project.
As is known From Help to make this it's necessary to call
LIB library /EXTRACT:member /OUT:objectfile
But I don't know exactly will it possible to use resulting file (.obj) in my project.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,161 Views

I believe your INTERFACE is missing a USE DFWIN statement
0 Kudos
mavlik
Beginner
1,161 Views

I believe your INTERFACE is missing a USE DFWIN statement

Thank you. It works.
A also try to use functions GetRValue, GetGValue and GetBValue.
In C++ they are declarated as macro:
#define GetRValue(rgb) (LOBYTE(rgb))
#define GetGValue(rgb) (LOBYTE(((WORD)(rgb)) >> 8))
#define GetBValue(rgb) (LOBYTE((rgb)>>16))
Is it possible to make something like this in Fortan?
I've declare three functions in .fi file of project:

INTERFACE
INTEGER(1) FUNCTION GETGVALUE(RGB)
INTEGER*4 RGB
END FUNCTION GETGVALUE
END INTERFACE

But I don't know how to make realization of functions, because of I can not find how to use type cast in Digital Visual Fortran.

0 Kudos
TimP
Honored Contributor III
1,161 Views
Quoting - mavlik

Thank you. It works.
A also try to use functions GetRValue, GetGValue and GetBValue.
In C++ they are declarated as macro:
#define GetRValue(rgb) (LOBYTE(rgb))
#define GetGValue(rgb) (LOBYTE(((WORD)(rgb)) >> 8))
#define GetBValue(rgb) (LOBYTE((rgb)>>16))
Is it possible to make something like this in Fortan?
I've declare three functions in .fi file of project:

INTERFACE
INTEGER(1) FUNCTION GETGVALUE(RGB)
INTEGER*4 RGB
END FUNCTION GETGVALUE
END INTERFACE

But I don't know how to make realization of functions, because of I can not find how to use type cast in Digital Visual Fortran.

You haven't shown your question about type cast clearly. I can't believe that even early DVF was missing things like TRANSFER, and even that is beyond what you would need here. Anyway, most of us would recommend against trying to find something which works only in DVF, not in standard Fortran.
That's not C++ you are quoting, it's some Microsoft macro stuff for C++. Wouldn't you do something like
IAND(rgb,z'ff')
IAND(ISHFT(rgb,-8),z'ff')
....
for similar effect in Fortran?
0 Kudos
mavlik
Beginner
1,161 Views
Quoting - tim18
That's not C++ you are quoting, it's some Microsoft macro stuff for C++. Wouldn't you do something like
IAND(rgb,z'ff')
IAND(ISHFT(rgb,-8),z'ff')
....
for similar effect in Fortran?

OK. Thanks, it's realy a way to solve this problem.
I don't know what is z'ff' (I can only guess) but I use in this way: GetRValue = IAND(rgb,#FF)....

Fortran is slightly strange language...
I need help in one more question..I try to declare a pointer on variable of array type...
In c++ It wil be so:
typedef TRGB[1000] arr
arr *p;

And then it's possible to address variable: (*p).r

In pascal:

type
Trgb = packed record
b,g,r : byte
end;

const
MaxPixelCountA = MaxInt div Sizeof(TRGB);
type
arr = array [0..MaxPixelCountA - 1] of TRGB;

var
p : ^arr;
brg:single;
........
brg:=0.3*GetRValue(p^[i + w * j].r)+0.59*GetGValue(p^[i + w * j].g)+0.11*GetBValue(p^[i + w * j].b);

In fortran I make so:

type T_RGB
byte b,r,g
end type T_RGB

type (T_RGB) arr(715827882) ! //MaxInt div 3
POINTER (P,arr)
And in main function try to refer: brg = p(1)%r

Fortran says that I have
Error: This name has not been declared as an array.


brg = loc(p(1)%r)
--------------^

0 Kudos
Paul_Curtis
Valued Contributor I
1,161 Views

! extract the components from the supplied colorRef
red = RSHFT(IAND(RGB, Z'00FF0000'), 16)
blue = RSHFT(IAND(RGB, Z'0000FF00'), 8)
green = IAND(RGB, Z'000000FF')

0 Kudos
mavlik
Beginner
1,161 Views
Quoting - Paul Curtis
! extract the components from the supplied colorRef

IscolorRef a file from DVF ?

How dod you make it?

0 Kudos
mavlik
Beginner
1,161 Views
Where can I ask my question(that is written above) about pointer variable and error?
type Parr
type(T_RGB) arr(10)
end type Parr

type(Parr), pointer :: P

0 Kudos
Steven_L_Intel1
Employee
1,035 Views
Quoting - mavlik

type T_RGB
byte b,r,g
end type T_RGB

type (T_RGB) arr(715827882) ! //MaxInt div 3
POINTER (P,arr)
And in main function try to refer: brg = p(1)%r

Fortran says that I have
Error: This name has not been declared as an array.


brg = loc(p(1)%r)
--------------^

You want arr(1)%r if you are going to use the integer pointer extension. P is just an integer containing an address.
0 Kudos
Reply