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

Error?

reneeculver
Einsteiger
3.845Aufrufe
The book arrived today!!!

Subroutine SetupExit
Use kernel32
Integer*4 FF
ff=SetupConsoleCntlrHandler(CloseWindow,.true.)
Return
End

Subroutine CloseWindow(number)
Integer*4 number
Return
End

I amcallingSetupExit but FFreturns a 1 which means an error ocurred. But what's the error?

Renee




0 Kudos
27 Antworten
reneeculver
Einsteiger
829Aufrufe
Good eyes, Ian.

But when changed the DECL

I get this error:

Error 1 error LNK2019: unresolved external symbol CLOSEWINDOW1 referenced in function SETUPEXIT ASUBS.obj

Renee
IanH
Geehrter Beitragender III
829Aufrufe

Put the same (make a copy)

!DEC$ ATTRIBUTES STDCALL :: CloseWindow1

line immediately after the EXTERNAL statement in the SetupExit subroutine.

In addition to changing how the stack is handled and the way arguments are passed, STDCALL also directs the compiler to decorate the names used by the linker in a particular way. Remembering that each program unit (main program, external subroutine or function) in Fortran is independently compiled - so when compiling SetupExit the compiler knows nothing about ConsoleHandler1 apart from what you tell it (in the absence of being told otherwise, the compiler will make certain "implicit" assumptions about what ConsoleHandler1 is - hence without the EXTERNAL it thought ConsoleHandler1 was a REAL variable). If you mark ConsoleHandler1 as STDCALL in one program unit but not in the other program unit then the name used by the linker for ConsoleHandler1 will vary from program unit to program unit.

With the "1" missing from your !DEC$... statement, both program units thought that ConsoleHandler1 had the default calling convention, both program units would have given the same linker name to ConsoleHandler1 and so the link succeeded. (The problem that remained then was that the default calling convention used by ifort was not what the Windows operating system requires for these handling routines.)

When the function and subroutine are inside a module (as per my example - note that a module is a new variety of program unit added with Fortran 90), then the various procedures inside the module (known as module procedures) are not compiled independently. When compiling SetupExit the compiler inherently knows all there is to know about CloseWindow (and vice versa) - similarly any program units that then USE the module also gain complete knowledge about the routines. This is one of the compelling benefits of modules.

Note that when you are adding new stuff to legacy code there's nothing to stop you from putting your new code in a module and just popping a USE statement at the very top of the program unit that's going to be calling your new code. Similarly, there's nothing stopping you from sticking IMPLICIT NONE in at the start of your module - it only applies inside the module itself.

reneeculver
Einsteiger
829Aufrufe
Ian,

I've copied your code into Exit1.f90.

MODULE RoutinesForHandlingTheConsole

IMPLICIT NONE ! Avoid bugs due to typos and confusion about type.

CONTAINS

SUBROUTINE SetupExit

USE KERNEL32, ONLY: SetConsoleCtrlHandler, BOOL, TRUE

INTEGER(BOOL) :: ff

ff = SetConsoleCtrlHandler(LOC(CloseWindow), TRUE)

END SUBROUTINE SetupExit

FUNCTION CloseWindow(number)

USE KERNEL32, ONLY: BOOL, DWORD, TRUE, FALSE

INTEGER(DWORD), INTENT(IN) :: number

INTEGER(BOOL) :: CloseWindow

!DEC$ ATTRIBUTES STDCALL :: CloseWindow

INTEGER(DWORD) number

SELECT CASE (number)

CASE (0) ! Ctrl c

PRINT "('Oi!! Stop pressing Ctrl-C!')"

CloseWindow = TRUE

CASE (1) ! Ctrl break

PRINT "('Ouch!! That Ctrl-Break hurt!')"

CloseWindow = TRUE

CASE (2) ! Console Window close

PRINT "('Wait a tick - I don''t want to go away!')"

CloseWindow = TRUE

CASE DEFAULT ! 5 for log off, 6 for shutdown -

PRINT "('Bye bye!!')"

CloseWindow = FALSE

END SELECT

END FUNCTION CloseWindow

END MODULE RoutinesForHandlingTheConsole

I thought I was home until I recieved the following error....

Error 1 error #6418: This name has already been assigned a data type. [NUMBER] D:\System Utilities\Adventure\Adventure\Adventure(intel)\Adventure\Exit1.f90 15

Where has "number" already been assigned a datatype?

Renee

IanH
Geehrter Beitragender III
829Aufrufe
I can see two lines that declare number to be of type INTEGER(DWORD). I suggest you delete the second one without the INTENT(IN) clause, that is immediately before the SELECT CASE statement.

Note that to put short sections of code into your posts you can use the little yellow pencil (I think it's actually supposed to be a fluoro highlighter pen) that is in the toolbar.
reneeculver
Einsteiger
829Aufrufe
Yes, you were right. I'll have to stop prograaming so late.

Now I have fixed that that problem....and...I think I have a linkage problem.

Error 1 error LNK2019: unresolved external symbol SETUPEXIT referenced in function MAIN__ AAMAIN.obj

How do I call it? I am currently calling it:

call SetupExit

Like that....

Renee
reneeculver
Einsteiger
829Aufrufe
I got it....

Renee
reneeculver
Einsteiger
829Aufrufe

I put the files back into where they used to be....Now I don't get a stack dump but I do hit a break point.

I'm willing to put this on hold for a while.....

Once again...thank you.

Renee

Antworten