Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
Important Update: Community Platform Migration​. Learn more​>
29647 Discussions

Failure in creating and using a DLL: Error R6034

Arjen_Markus
Honored Contributor II
1,397 Views
Hello,

I am trying to create and use a simple Fortran DLL butthat results in an error message
"R6034: An application has attempted to load the C runtime library incorrectly"

This is with Intel Fortran 11.1 on Windows XP.

Here are my compile and build commands:

ifort mydll.f90 -dll
ifort myprogram myprogram.f90 mydll.lib

and the code:

--- mydll.f90 ---

module prng_factory

implicit none

integer, parameter :: type_uniform = 1

integer, parameter :: type_exponential = 2

type, abstract :: prng

! No data

contains

procedure(get_next), deferred :: get

end type

abstract interface

real function get_next( params )

import :: prng

class(prng) :: params

end function get_next

end interface

type, extends(prng) :: prng_uniform

real :: xmin, xmax

contains

procedure :: get => get_uniform

end type

type, extends(prng) :: prng_exponential

real :: xmean

contains

procedure :: get => get_exponential

end type

contains

real function get_uniform( params )

!DEC$ attributes dllexport :: get_uniform

class(prng_uniform) :: params

real :: r

call random_number( r )

get_uniform = params%xmin + (params%xmax-params%xmin) * r

end function get_uniform

real function get_exponential( params )

!DEC$ attributes dllexport :: get_exponential

class(prng_exponential) :: params

real :: r

call random_number( r )

get_exponential = -params%xmean * log( r )

end function get_exponential

function prng_create( type, param1, param2 )

!DEC$ attributes dllexport :: prng_create

integer :: type

real :: param1

real, optional :: param2

class(prng), pointer :: prng_create

type(prng_uniform), pointer :: uniform

type(prng_exponential), pointer :: exponential

select case (type)

case (type_uniform)

allocate( uniform )

prng_create => uniform

case (type_exponential)

allocate( exponential )

prng_create => exponential

case default

nullify( prng_create )

end select

select type (prng_create)

type is (prng_uniform)

if ( present(param2) ) then

prng_create%xmin = param1

prng_create%xmax = param2

else

prng_create%xmin = 0.0

prng_create%xmax = param1

endif

type is (prng_exponential)

prng_create%xmean = param1

end select

end function prng_create

end module prng_factory


--- myprogram.f90 ---

program test_prng_factory

use prng_factory

class(prng), pointer :: p

integer :: i

p => prng_create( type_uniform, 1.0, 2.0 )

do i = 1,10

write(*,*) p%get()

enddo

p => prng_create( type_exponential, 10.0 )

do i = 1,10

write(*,*) p%get()

enddo

end program test_prng_factory


This works fine on Linux (using Intel Fortran 12) and with gfortran on Windows XP (but then
I do not have to worry about the DLLEXPORT stuff).

What am I doing wrong?

Regards,

Arjen

0 Kudos
8 Replies
mecej4
Honored Contributor III
1,397 Views
No problems building and running with 11.1.070 or 12.0.4.196 (both targeting IA32) on W7-X64.

EIther you are using an earlier version than 11.1.070, or there is some problem with the configuration/environment.
0 Kudos
Arjen_Markus
Honored Contributor II
1,397 Views
Good to hear that. I just turned off the machine I ran it on, so I can not check it at the moment.

I wil check further tomorrow.

Regards,

Arjen
0 Kudos
Steven_L_Intel1
Employee
1,397 Views
You need to add /libs:dll to the link of the main program. The DLL implicitly has that because of -dll. What is happening is that your EXE does not have the correct manifest to cause loading of the MSVCRT DLL but it is also linking to the static MSVC library. The effects of this on XP are what you saw. On Windows 7 you may get a "DLL not found" error.
0 Kudos
Arjen_Markus
Honored Contributor II
1,397 Views

Thanks! I will try that - that serves me right for avoiding the Visual Studio environment ;). But for such
small programs I find it a very heavy environment.

Regards,

Arjen

0 Kudos
Arjen_Markus
Honored Contributor II
1,397 Views

Yes, that solved the problem! I removed the DLLEXPORT directives from the get_uniform and get_exponential functions and the program still worked. I guess these are not required, because they are resolved at run-time?

Regards,

Arjen

0 Kudos
Steven_L_Intel1
Employee
1,397 Views
If the procedure is not called from outside the DLL, you don't need DLLEXPORT.
0 Kudos
Arjen_Markus
Honored Contributor II
1,397 Views
Well, I am trying to understand the consequences - if there are any - of having an object with
type-bound procedures in a DLL. I guess that getting back the object from an (exported)function/subroutine
in the DLL is enough to make these type-bound procedures available in the calling program. They are
not invoked directly from my program.

I see some interesting possibilities here (a "plugin archtecture").

Regards,

Arjen

0 Kudos
Steven_L_Intel1
Employee
1,397 Views
Right. The type-bound procedures end up as entries in a table with references resolved when the DLL is linked. The use of the TBPs through the type don't require DLLEXPORT. If you called the procedures directly by name, passing the object explicitly, you would need DLLEXPORT.
0 Kudos
Reply