I have a very similar problem to the one described here: Make external functions accessible for other functions/modules in Fortran
I'm working with a DLL compiled from Fortran source code, using the Lahey/Fujitsu LF95 compiler and I'm trying to store a global reference to an external callback function (function pointer) so that it can be called at a later time from other functions in the Fortran DLL.
The scenario is something like this:
the host application invokes a subroutine (procedure) from the Fortran DLL and passes a reference to the callback function
a reference to the callback function should be stored as a global
later, the host application may call various functions from the Fortran DLL and these functions need to invoke the callback function, calling into the host application.
The problem is that the accepted answer from the question doesn't compile with the Lahey Fortran compiler. Apparently, there are quite some differences between the Intel compiler and the LF95 compiler.
I did get the callback reference to work fine in a single subroutine, like this:
subroutine testcallback(cbk)
dll_export :: testcallback ! Lahey LF95 extern declaration to export this function
character(len=*) :: text
interface
subroutine cbk (string, length)
character(len=*), intent (in) :: string
integer, intent (in) :: length
end subroutine cbk
end interface
text = "Hello World"
call cbk(text, len(text)) ! invoke the cbk callback; works very well
return
end
Invoking this function from the host application (C# in my case but that's inconsequential) works very well. I can pass in a function reference (delegatae in C#) and Fortran makes the call correctly and I get the expected results.
The issue is that I can't seem to be able to move the interface declaration outside of testcallback, and then subsequently call the cbk from a different Fortran function.
Here's an example of what I would want to accomplish:
subroutine setcallback(cbk)
dll_export :: setcallback ! Lahey LF95 extern declaration to export this function
interface
subroutine cbk (string, length)
character(len=*), intent (in) :: string
integer, intent (in) :: length
end subroutine cbk
end interface
! instead of calling cbk here, I'd like to save a reference to it and make it
! available to other functions..
return
end
subroutine testcallback()
dll_export :: testcallback ! Lahey LF95 extern declaration to export this function
character(len=*) :: text
text = "Hello World Again"
! somehow I want to be able to invoke the stored reference to cbk here
!
call cbk(text, len(text)) ! this obviously doesn't work like this
return
end
In closing I'd like to add that moving away from the LF95 compiler is not an option at this time. If anybody knows how to handle this I would very much appreciate it!
Related
I tried the following code to get the code to work correctly. It seems I need to write an interface to avoid mistaken results. I wrote the following, but it does not pass the compiling stage. The errors are the following: (use gfortran compiler)
fit.f90:34.16:
TYPE(spec), INTENT(IN) :: SMP
1
Error: Derived type 'spec' at (1) is being used before it is defined
fit.f90:35.12:
REAL(q), INTENT(OUT) :: RES
1
Error: Symbol 'q' at 1 has no IMPLICIT type
...
Here is the compilable code to illustrate the issue.
MODULE prec
INTEGER, PARAMETER :: q=8
END MODULE prec
MODULE MOD_FIT
USE prec
INTEGER, PARAMETER :: NO_NI=200
TYPE spec
! source of fitting
INTEGER NW
COMPLEX(q), POINTER :: W(:),G(:)
! how spectrum is parametrized
INTEGER NO_NM ! continuous points labeled as 1,2,3,...,NO_NM
REAL(q), ALLOCATABLE :: O_N(:),O_D(:) ! frequency
REAL(q), POINTER :: A_N(:),B_N(:),A_D(:) ! A(Omega)
END TYPE
TYPE(spec) SMP
INTERFACE
SUBROUTINE NNLS_CMPLX(SMP,RES,RES_V)
IMPLICIT NONE
TYPE(spec), INTENT(IN) :: SMP
REAL(q), INTENT(OUT) :: RES
COMPLEX(q), OPTIONAL, INTENT(OUT) :: RES_V(SMP%HN)
END SUBROUTINE NNLS_CMPLX
END INTERFACE
CONTAINS
SUBROUTINE NNLS_CMPLX(SMP,RES,RES_V)
IMPLICIT NONE
TYPE(spec) :: SMP
REAL(q) :: RES
COMPLEX(q), OPTIONAL :: RES_V(*)
RES=0
IF(PRESENT(RES_V)) RES_V(1)=0
END SUBROUTINE NNLS_CMPLX
END MODULE MOD_FIT
PROGRAM MAIN
USE prec; USE MOD_FIT
REAL(q) PK_RES
COMPLEX(q) RES_V(4)
CALL NNLS_CMPLX(SMP,PK_RES,RES_V)
END
Having an explicit interface means that the compiler knows how the called subroutine or function (procedure) looks like.
Explicit interfaces should not be normally provided by an interface block, that is the thing:
interface
...
end interface
but by placing the procedures in modules instead.
You definitely cannot use an interface block for a module procedure (a procedure placed inside a module). Interface block tells that there is some external procedure somewhere with the properties you declare in the interface block. But your procedure is not external, it is in a module.
Just remove the interface block and it should work.
Just a suggestion: use small caps and indentation in your code. It is very difficult to read as it stands.
To explain the actual error message: As francescalus comments, interface blocks have a separate scope. If they are placed in a module, they do not see the other contents of the module. That's why the compiler complains it does not know what spec and q are.
When I try to compile code under the statement with ifort it returns error as:
error #8169: The specified interface is not declare
But it works perfectly on gfortran, for some reason I have to use intel compiler to compile this work. The language I am using is Fortran. The reason for this is that the 'ifort' compiler does not see the variables in Interface. So I develop a module called Var to do fix that. And Use it in every blocks. But it returns error:
This USE statement is not positioned correctly within the scoping unit.
The var module is like following:
MODULE VAR
CHARACTER(50) :: callbackID
END MODULE
how can I fix the problem thanks alot! My compiler version is ifort 12.1.0
MODULE DEMO
USE VAR
INTERFACE
SUBROUTINE callback_prototype(callbackID)
USE VAR
CHARACTER(*) :: callbackID
END SUBROUTINE callback_prototype
END INTERFACE
PROCEDURE( callback_prototype ), POINTER :: f_ptr => NULL()
CONTAINS
SUBROUTINE set_callback(func)
IMPLICIT NONE
EXTERNAL :: func
f_ptr => func
call HELLO
END SUBROUTINE
SUBROUTINE invoke_callback(callbackID)
CHARACTER(*) :: callbackID
if (associated(f_ptr)) call f_ptr(callbackID)
END SUBROUTINE
SUBROUTINE HELLO
IMPLICIT NONE
!dosomthing
END SUBROUTINE
END MODULE
The code as presented is not legal fortran. The use statement inside the interface body makes accessible a name that is the same as a dummy argument. This violates the scoping rules of the language.
The use statement inside the interface body would appear to be superfluous.
I don't see the reason why you want the use statement in the interface in the first place. Even the interface can be skipped, because you have the right procedure accessible:
PROCEDURE( invoke_callback ), POINTER :: f_ptr => NULL()
In a Fortran 2003 module I'm defining a type called t_savepoint and, later, I want to define an interface for a subroutine called fs_initializesavepoint, which takes an object of type t_savepoint as only argument.
Here is the code for the whole module:
module m_serialization
implicit none
type :: t_savepoint
integer :: savepoint_index
real :: savepoint_value
end type t_savepoint
interface
subroutine fs_initializesavepoint(savepoint)
type(t_savepoint) :: savepoint
end subroutine fs_initializesavepoint
end interface
end module m_serialization
The reason why I want such an interface is that later on I will make this fortran module interoperate with C.
If I try to compile it (gfortran-4.7.0), I get the following error message:
type(t_savepoint) :: savepoint
1
Error: The type of 'savepoint' at (1) has not been declared within the interface
The error disappears if I move the definition of the type inside the subroutine; but if then I want to use the same type within many subroutines, should I repeat the definition in all of them?
Thank you in advance.
EDIT: a solution would be to move the definition of the type onto another module and then to use it in every subroutine. However I don't like this solution too much, because the type t_savepoint and the subroutines are part of the same conceptual topic.
Rightly or wrongly in an interface block you don't have access to the environment by host association. To fix this you need to import the datatype exlicitly:
[luser#cromer stackoverflow]$ cat type.f90
module m_serialization
implicit none
type :: t_savepoint
integer :: savepoint_index
real :: savepoint_value
end type t_savepoint
interface
subroutine fs_initializesavepoint(savepoint)
Import :: t_savepoint
type(t_savepoint) :: savepoint
end subroutine fs_initializesavepoint
end interface
end module m_serialization
[luser#cromer stackoverflow]$ gfortran -c type.f90
This is f2003.
However I suspect the way you have put this suggests you are not going about coding this up the best way. Better is simply to put the routine itself in the module. Then you don't need bother with the interface at all:
module m_serialization
implicit none
type :: t_savepoint
integer :: savepoint_index
real :: savepoint_value
end type t_savepoint
Contains
Subroutine fs_initializesavepoint(savepoint)
type(t_savepoint) :: savepoint
Write( *, * ) savepoint%savepoint_index, savepoint%savepoint_value
End Subroutine fs_initializesavepoint
end module m_serialization
[luser#cromer stackoverflow]$ gfortran -c type.f90
Given that modules are really designed to deal with connected entities this is really the way to do it in Fortran. It also has the advantage of only requiring a f95 compiler, so is universally available (though admittedly import is commonly implemented)
While writing a library to read image values, I have the following problem:
I defined a new type called realimage. Within this type a function is referenced, which returns an array as a result.
module typedefinition
implicit none
type realimage
integer :: byteorder = 0
contains
procedure :: initialize => initializereal
procedure :: pxvalues => pxvaluesreal ! Array valued function
end type realimage
contains
function pxvaluesreal(this, x, y) result(val)
implicit none
type(realimage) this
real val(5)
integer :: x, y
...
end function
end module
Compiling the module with gfortran and calling the function with image1%pxvalues(x,y), I always get the following error message:
main.f95: In function ‘testtype’:
main.f95:15: internal compiler error
If I directly call the function in the main program (pxvaluesreal(image1,x,y)), everything works fine.
Is it possible to define the array dimension in the type definition in order to tell the compiler, which are the dimesions of the return value of the function?
Internal compiler errors are always due to a compiler bug. If you are using a recent version of gfortran you should consider reviewing their list of open bugs and perhaps filing a bug report.
Beyond that - your code is not standard compliant - the passed object 'this' must be polymorphic (declare it with CLASS rather than TYPE). Otherwise your specification of the size of the array function result is correct - when you reference the pxvalues binding the compiler knows that the size of the function result is 5 as it 'knows' the interface of the specific procedure pxvaluesreal that the binding is associated with.
I have written a Perl XS wrapper for a C library consisting of about ~80
functions. Right now my general strategy is to substitute the error from a C
function with PL_sv_undef and the calling Perl code has to check explicitly
whether the return is not undef. (For some C functions it is more complicated
as I convert their output into a HV/AV and use empty list to report the error.)
Now as I moved to writing bigger Perl scripts using that library, I want to
simplify the error handling and use e.g. the usual eval {}/die exception-like
mechanism to handle errors.
At the moment a simple XSUB in my XS look like that:
SV *
simple_function( param1, param2 = 0, param3 = 0)
int param1
int param2
int param3
CODE:
int rc;
rc = simple_function( param1, param2, param3 );
RETVAL = (rc == 0) ? &PL_sv_yes : &PL_sv_undef;
OUTPUT:
RETVAL
I have seen that some modules have global flag like "RaiseError" to die on
errors but failed to find any example I can borrow from. The few modules I have
found handle the "RaiseError" flag inside the .pm, not inside the .xs, and
thus allowed to use the Perl's die. In my case that is rather hard to
implement inside the .pm as many functions require special error checks. That
would also lead to code duplication as the checks are already present inside the XS.
I found nothing relevant in the perlxs/perlguts documentation. In particular, I have seen calls to Perl_croak() in the .c generated from my .xs, but failed to locate any documentation for the function.
What is the XS' analog of the Perl's die? Or how else can the XSUB report to Perl
run-time that the function has failed and there is no RETVAL to return? How to properly set the $#?
Perl_croak() is documented here on the perlapi man page. As the example on that page shows, you can either pass it a message string, or you can manually set $# to an exception object and pass NULL.