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

A reference to path//myDLL.dll could not be added.please make sure that the file is accessible,and that is a valid assembly or

John_C_
Beginner
6,648 Views

 1. have some Fortran .f90 files.

2 I installed visual Fortran compiler in visual studio 2015

  1. I created library DLL empty project.

  2. I added all .f90 and .f files to the project.

5 I compiled the project.

6 now I have myproject.dll file.

7.I created a web application.

8 I try to add myproject.dll to references.

9.I got this error in visual studio environment before compile. :

reference manager: A reference to path//myDLL.dll could not be added.please make sure that the file is accessible,and that is a valid assembly or COM component.

Which project type knows my dll?.is there any error in compile of my dll?therefore what should I do?

Best regards

0 Kudos
44 Replies
John_C_
Beginner
951 Views
Hi, I want to use asp.net C# web application instead of vb.net as above for calling dlls via fortran codes.is there any example sample or link? Which important modifications should i do on vb.net to make c#.NET and after that asp.net c# web application?please someone guide me. I found this link for c# :https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/741239 Best regards Any help will be appreciated.
0 Kudos
John_C_
Beginner
951 Views

I want to migrate from VB.Net to C#.These are my codes:

Module1.vb file:

 

Module Module1
    REM Use ByVal to pass strings unless the called routine expects BSTR structures
    
    Public Declare Auto Sub electrostatica3D Lib "FCALL.DLL" _
  (ByVal DBL_IN() As Double, ByVal STR_IN As String, ByVal DBL_OUT() As Double)

End Module

fcall.f90 fortran file:

subroutine electrostatica3D(DBL_IN, STRING_IN, DBL_OUT)
    
  use malla_3DP1
  use electros3D
  use external_electros3D
  use derivados3D
  use resolucion_sistema_lineal
     
  implicit none
  
  ! Specify that DLL_ROUT is exported to a DLL
! and that the external name is 'DLL_ROUT'
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL :: electrostatica3D
!DEC$ ATTRIBUTES ALIAS:'electrostatica3D' :: electrostatica3D

REAL(8), INTENT(IN) :: DBL_IN(0:3)
CHARACTER(10), INTENT(IN) :: STRING_IN
!DEC$ ATTRIBUTES REFERENCE :: STRING_IN
! When VB passes in a "ByVal String", it passes the address
! of a NUL-terminated string, similar to what C would do,
! and no separate length.  The REFERENCE attribute tells
! Fortran not to expect a length.  In order to use a function
! such as INDEX, we need to supply some maximum length to Fortran
! which should be at least as long as the longest expected string.
REAL(8), INTENT(OUT) :: DBL_OUT(4)

REAL(8) STRVAL
INTEGER IOS, STRLEN
  
  integer          :: info
  double precision :: suma
  integer          :: i

  
  STRLEN = INDEX(STRING_IN, CHAR(0)) - 1

! Convert STRING_IN to a double.  If we get an error, we'll
! supply 1.0 as a default

READ (STRING_IN(1:STRLEN), *, IOSTAT=IOS) STRVAL
IF (IOS /= 0) STRVAL = 1.0
DBL_OUT = STRVAL * DBL_IN

call arint3D ()

 return
end

Form1.vb file:

Public Class Form1
    Inherits System.Windows.Forms.Form

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim DBL_IN(4) As Double
        Dim DBL_OUT(4) As Double
        Dim MULTIPLIER As String
        ' Note that in VB, arrays are zero-based.
        DBL_IN(0) = 1.0
        DBL_IN(1) = 2.0
        DBL_IN(2) = 3.0
        DBL_IN(3) = 4.0
        MULTIPLIER = "2.0"
       
        Call electrostatica3D(DBL_IN, MULTIPLIER, DBL_OUT)

        TextBox1.Text = DBL_OUT(0)
        TextBox2.Text = DBL_OUT(1)
        TextBox3.Text = DBL_OUT(2)
        TextBox4.Text = DBL_OUT(3)
    End Sub

 

use C# code as :

using System;

using System.Runtime.InteropServices;
namespace Console_use_integrate{
    class Program
    {


        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate float ActionRefInt(ref float n);

        public ActionRefInt callbackHandler;

        public Program()
        {
            callbackHandler = new ActionRefInt(square);
        }

        public float square(ref float n)
        {
            return n*n;
        }


        static void Main(string[] args)
        {
            Program myProg2 = new Program();

            float a = 1f;
            float b = 3f;
            int step = null;
            float result;
            Console.WriteLine("Interval  from {0} to {1} ", a, b);
       
result = integrate_Dll(myProg2.callbackHandler, a,  b,  System.IntPtr.Zero)
            Console.WriteLine("integration result is {0}",result);
            Console.ReadKey();
        }


       [DllImport(@"FCALL.DLL", CallingConvention = CallingConvention.Cdecl, 
EntryPoint = "electrostatica3D")]
public static extern float electrostatica3D([MarshalAs(UnmanagedType.FunctionPtr)] ActionRefInt callBack,
float a, float b, ref int c);
[DllImport(@"FCALL.DLL", CallingConvention = CallingConvention.Cdecl, 
EntryPoint = "electrostatica3D")]
public static extern float electrostatica3D([MarshalAs(UnmanagedType.FunctionPtr)] ActionRefInt callBack,
float a, float b, System.IntPtr c);

    }

    }

 

and changing 
 

float a, float b, System.IntPtr c


to something like below but in C# format
 

ByVal DBL_IN() As Double, ByVal STR_IN As String, ByVal DBL_OUT() As Double

and a little modification maybe needed.

so what should I do?

I found a link maybe it's useful Converting FORTRAN code to C# https://www.codeproject.com/Questions/491373/ConvertingplusFORTRANpluscodeplustoplusC

Regards

0 Kudos
Steve_Lionel
Honored Contributor III
951 Views

I would suggest asking in a C# forum. Your question isn't really about Fortran. There is probably not a lot of VB/C# expertise here.

0 Kudos
FortranFan
Honored Contributor II
951 Views

John C. wrote:

I want to migrate from VB.Net to C#.  These are my codes ..

@John C.,

I think it will get quite wordy and rather difficult for anyone trying to explain what you should do to migrate to C#.  Already this post and this thread has become too long for me.

You keep pursuing an approach where "a little modification" may be all that is needed to do what you want - in my opinion, this is entirely inappropriate and also inadequate.  .NET development is an area for which there are lots and lots of resources available, including free ones online as you have found, and if you are unwilling to parse those resources and apply the learnings from them by yourself for your own needs or unable to do so on account of time or inclination or whatever, you should look to outsource the work to some IT business perhaps e.g., contract programmer(s).  Moreover your questions and needs have more to do with .NET than Fortran and so you should turn to MSDN-type of forums with a focus on .NET and P/Invoke for your needs, as suggested by Steve Lionel upthread.

To make it a little easier in your pursuit, attached find an attachment of a zip file with an example of a C# Windows Form application that utilizes a Fortran DLL on the backend to do some calculations.   It is based on Visual Studio 2017 with Intel Fortran compiler 18.0 beta update 1; you can figure out how to use this example with your version of Visual Studio and the Fortran compiler.  There is little to no documentation by the way in the example, it is deliberate for my expectation is anyone who has made some attempts to learn Fortran and C and also to review .NET development will be able to use this as a rough guide for their needs which is all this is meant for, a crude go-by.  The example is based loosely on your previous post but it uses a few code constructs that are somewhat different, it assumes certain things, and it does require a wee bit of attention.  Anyone with an eye for a bit of detail though should be able to change or extend it for their needs, especially considering the wealth of information on ,NET online.

The code in Fortran is structured to interoperate with a companion C processor and to accept a double precision floating point input as value along with a multiplier in a C-style string 'char *' format and it parses the info to return a result that is the product of the two.  The project in the Visual Studio solution is configured to build a DLL and it does a post-build event to copy the DLL file to TESTPATH, an environment variable pointing to a folder on the Windows PATH.

module m

   use, intrinsic :: iso_c_binding, only : c_char, c_int, c_double, c_ptr, c_f_pointer
   
   implicit none

contains

   subroutine Fsub( inval, ptr_s, lens, outval, fstat ) bind(C, name="Fsub")

      ! Argument list
      real(c_double), intent(in), value :: inval
      type(c_ptr), intent(in), value    :: ptr_s
      integer(c_int), intent(in), value :: lens
      real(c_double), intent(inout)     :: outval
      integer(c_int), intent(inout)     :: fstat

      fstat = 0
      if (lens <= 2) then
         fstat = 1
         return
      end if
      
      blk: block
         
         character(kind=c_char, len=lens), pointer :: s_ptr => null()
         real(c_double) :: mult
         integer :: istat
         character(len=10) :: fmtstr
         character(len=256) :: imsg
         
         call c_f_pointer( cptr=ptr_s, fptr=s_ptr )
         
         write ( unit=fmtstr, fmt="(*(g0))", iostat=istat ) "(G", lens, ".", lens-2, ")"
         if ( istat == 0 ) then
            read ( unit=s_ptr, fmt=fmtstr, iostat=istat, iomsg=imsg ) mult
         end if
         s_ptr => null()
         if ( istat /= 0 ) mult = 1.0_c_double
         
         outval = inval*mult

      end block blk

      return

   end subroutine Fsub

end module m

The project in C# is configured as a Windows Form application, it has a static class that helps interoperate with the Fortran DLL as follows:

using System;
using System.Runtime.InteropServices;

namespace WinFormsApp
{

   static class Fdll
   {

      // Overload methods for the optional parameter
      [DllImport("Fdll.dll", CallingConvention = CallingConvention.Cdecl)]
      internal static extern void Fsub(double val, System.IntPtr ptrmult, int lens, ref double result,
         ref int fstat);

   }
}

The project includes all the wiring toward a user-interface (UI), explanations for which can be found in many, many places online; the primary code for a button-driven action to invoke Fortran code for the calculation is:

      private void btnCalc_Click(object sender, EventArgs e)
      {

         var irc = System.Windows.Forms.DialogResult.None;

         if (!tbval_valid)
         {
            irc = MessageBox.Show("Enter valid numeric input for Value", "Field Value", MessageBoxButtons.OK);
            tbVal.Select(0, 0);
            tbVal.Focus();
            return;
         }

         if (!tbmult_valid)
         {
            irc = MessageBox.Show("Enter valid numeric input for Multiplier", "Field Multiplier", MessageBoxButtons.OK);
            tbVal.Select(0, 0);
            tbMult.Focus();
            return;
         }

         System.IntPtr ptr_to_smult = System.IntPtr.Zero;

         try
         {
            tbOut.Text = string.Empty;
            result = 0.0;
            string smult = mult.ToString(fmt_mult);
            ptr_to_smult = Marshal.StringToHGlobalAnsi(smult);
            int fstat = 0;
            Fdll.Fsub(val, ptr_to_smult, smult.Length, ref result, ref fstat);
            if (fstat == 0)
            {
               tbOut.Text = Convert.ToString(result);
            }
            else
            {
               irc = MessageBox.Show("Fsub procedure in the Fortran DLL returned an error: fstat = " + fstat.ToString(),
                  "Button Calculate", MessageBoxButtons.OK);
            }
         }
         catch (Exception ex)
         {
            irc = MessageBox.Show(ex.Message, "Button Calculate", MessageBoxButtons.OK);
         }
         finally
         {
            if (ptr_to_smult != System.IntPtr.Zero) Marshal.FreeHGlobal(ptr_to_smult);
         }

      }

Upon execution, the program generates a form 

input.png

and the user can manipulate the fields and controls as appropriate to work the application.

One can now review ASP.NET material online and modify this example to build an ASP.NET web application.

593746

0 Kudos
John_C_
Beginner
951 Views
Dear @FortranFan , Would you please make changes that I could use your project in Visual studio 2012 and Intel.Parallel.Studio.XE.2016. Because my other project sources are under VS2012 and Intel.Parallel.Studio.XE.2016.also i have many problems with visual studio 2015 i couldn't run it in visual studio 2015 ,either Visual Studio 2017 with Intel Fortran compiler 18.0 beta update 1 Now i am trying to install visual studio 2017 and intel.parallell 2017 ,is it necessary to install intel visual compiler 18? reagrds
0 Kudos
FortranFan
Honored Contributor II
951 Views

John C. wrote:

.. Would you please make changes that I could use your project in Visual studio 2012 and Intel.Parallel.Studio.XE.2016. ..

@John C.

I do not have "Visual studio 2012".

Please do not address me any further in any of your posts.

0 Kudos
John_C_
Beginner
951 Views
Now i am trying to install visual studio 2017 and intel.parallell 2017 ,is it necessary to install intel visual compiler 18?
0 Kudos
mecej4
Honored Contributor III
951 Views

Parallel Studio 2018 is still in beta, and may be released in September 2017. However, you probably do not need it (yet). Just install Parallel Studio (or Composer) 2017 Update 4 for now.

0 Kudos
John_C_
Beginner
951 Views
Hi, is there DLL path important? how should we give access to DLL file?there is an error said visual studio could not find dll ...,how should we do in visual studio? best regards
0 Kudos
Steve_Lionel
Honored Contributor III
950 Views

You can't do this in Visual Studio. Windows looks for DLLs in the following locations:

  • Current directory (for a VS project that's the project directory)
  • Directory where the EXE resides
  • Directories named in the PATH environment variable
  • The Windows directory
  • The Windows\System32 directory

Yes, the DLL path is important.

0 Kudos
John_C_
Beginner
950 Views
Hi, I run above uploaded project in visual studio 2017 and parallel studio 2017.I got this error when I start the project: Severity Code Description Project File Line Suppression State Error error PRJ0019: A tool returned an error code from "Performing Post-Build Event..." (F = file, D = directory)? Project But when next time I copy the DLL into Directory where the EXE resides everything "works right" ( successfully ) . What should I do non getting this error and the project access DLL automatically (Not manually as I do)? Best Regards
0 Kudos
John_C_
Beginner
950 Views
Hi , What is the reason for this error: Unable to find an entry point named 'electrostatica3D' in DLL 'Dll1.dll' Regards
0 Kudos
gib
New Contributor II
950 Views

That means DLL1.dll does not include a subroutine or function named 'electrostatica3D'.

To enable the .exe to find the DLL when it's not in the same directory as the .exe, add the location of the DLL to the environmental variable PATH.  If you don't know how to do this, google it.  You can't expect people here to answer every little question, when it's quite feasible for you to find the answer yourself.

0 Kudos
FortranFan
Honored Contributor II
950 Views

John C. wrote:

.. I run above uploaded project in visual studio 2017 and parallel studio 2017.I got this error when I start the project:

Severity Code Description Project File Line Suppression State
Error error PRJ0019: A tool returned an error code from "Performing Post-Build Event..." (F = file, D = directory)? Project

.. What should I do non getting this error and the project access DLL automatically (Not manually as I do)?  ..

Quote #25 above with the attachment and details on the C# example also included the statement

"The project in the Visual Studio solution is configured to build a DLL and it does a post-build event to copy the DLL file to TESTPATH, an environment variable pointing to a folder on the Windows PATH."

0 Kudos
John_C_
Beginner
950 Views

I use these lines of code:
 

 ! YOUR CODE HERE
    module me

   use, intrinsic :: iso_c_binding, only : c_char, c_int, c_double, c_ptr, c_f_pointer
   
   implicit none

contains

   subroutine elecx( ) bind(C, name="elecx")

      
   !  YOUR CODE HERE start
   
   !program ppalelectros3D


  use fich_electros3D
  use electros3D
  use cargavol
  use cargacur
  use cargapun
  use permitividad
  use bloqueo
  use derivados3D        
  use malla_3DP1
  use external_electros3D
  use module_writeVTU
  use comprobaciones
  use module_convers
  use module_fem_extract
  use module_conver3d, only: conver3d
  use LIB_VTK_IO_READ
  use module_readUNV
  use module_compiler_dependant

  implicit none
  integer :: i,istat, p, nnod,DIMS,LNN,LNV,LNE,LNF,nnd,nco,npieces,nverteta,iformat
  integer, allocatable :: nn(:,:)
  real(real64), allocatable :: evtun(:)   

!---------------------------------------------------------------------------
!                            INPUT DATA                                    
!---------------------------------------------------------------------------

   if (command_argument_count() == 0) then
       call endat3D()
   else
       call readxml()
   end if

! INPUT DATA VERIFICATION, FOR ENDAT & READXML  
   if (.not. comprueba()) then
      write(error_unit,*) 'Input data check failed'
      stop 1
   else
      write(output_unit,*) 'Input data check passed'
   endif
   
   call calculate_funs()

! 0.0 IS ASSIGNED TO THE LAST VERTEX IN CASE OF NOT HAVING DIRICHLET CONDITIONS  
   if (blocking_node() < 0) then
      write(error_unit,*) 'Error assigning blocking node'
      stop 1
   endif 
   
!---------------------------------------------------------------------------
!                     ELECTROMAGNETIC MESH READING                    
!---------------------------------------------------------------------------
   call calindc(indc,inda)

   p = index(fichma, '.', back=.true.)
   if  (p == 0) stop 'Mesh file has not extension: unable to identify mesh format'
   select case (lcase(fichma(p+1:len_trim(fichma))))
   case('mfm')
     iformat=1
     call leema3D(iformat)
   case('mum')
     iformat=2
     call leema3D(iformat)
   case('unv')
     call readUNV(fichma,nel,nnod,nver,dims,LNN,LNV,LNE,LNF,nn,mm,nrc,nra,nrv,z,nsd)
     call conver3d(nel, nver, mm, z, nemm, det, binv, ib, jb)
   case default
     stop 'Unrecognized mesh file extension'
   end select
   call alloc_after_mesh()
   
!---------------------------------------------------------------------------
!                     TEMPERATURE READING                    
!---------------------------------------------------------------------------
   if (iopteta == 1) call leetmp()

!---------------------------------------------------------------------------
!                            COMPUTATIONS                                
!---------------------------------------------------------------------------
   if (iopblo.eq.1.and.iopblo1.eq.1) then
      call calprebloqueof(nrd,irefd)
   endif
   if (iopblo.eq.1.and.iopblo2.eq.1) then
      call calprebloqueoc(blofron%numero,blofron%referencias)
   endif

   call electrostatica3D()
   
   if(allocated(vexac))deallocate(vexac)
   allocate(vexac(nver),stat=ierror)
   if (ierror.ne.0) then
      print*,'Error while allocating array vexac',nver
      stop 1
   endif

   if(allocated(err))deallocate(err)
   allocate(err(nver),stat=ierror)
   if (ierror.ne.0) then
      print*,'Error while allocating array err',nver
      stop 1
   endif

!      call wrtcmp(nver,sol,10,fichsol)
!      call writeVTU(nel,nver,mm,z,'tetra',sol,'solucion','scalar', &
!             'node',trim(fichsol)//'.vtu')

! -1: mixed functions
! 0: no data
! 1: User defined / Function defined by user
! ...
   if (dir%funs > 1.or.&
       neu%funs > 1.or.&
       vol%funs > 1.or.&
       sup%funs > 1.or.&
       cur%funs > 1) then
      
      do i=1,nver
         vexac(i) = fexac(z(1,i),z(2,i),z(3,i))
         err(i)   = dabs(vexac(i)-sol(i)) 
      enddo

      if (dir%funs == 7) then ! 'Example 6'
         vexac(376) = sol(376)
         vexac(193) = sol(193)
         err(193)   = dabs(vexac(193)-sol(193))
         err(376)   = dabs(vexac(376)-sol(376))
      elseif (dir%funs == 6) then ! 'Example 5'
         vexac(1292) = sol(1292)
         err(1292)   = dabs(vexac(1292)-sol(1292))
      endif

      call norl2_3D(sol,xnorexac)
      call norl2_3D(vexac,xnorexac)
      call norl2_3D(err,xnorerr)
      rel = xnorerr/xnorexac
      print*,'Relative error (%)',100*rel
        
   endif

! COMPUTATION OF THE ELECTRIC FIELD 
   call ef()    

!---------------------------------------------------------------------------
!                            RESULTS OUTPUT                             
!---------------------------------------------------------------------------
   call wrtcmp(nver,sol,10,fichsol)

   call writeVTU(nel,nver,mm,z,'tetra',sol,'Potential (V)','scalar', &
                                  'node',trim(fichsol)//'.vtu')

   call wrtcmpv(nel,e,10,fichgradsol)

   if(allocated(evtu))deallocate(evtu)
   allocate(evtu(3*nel),STAT=istat)
   if (istat.ne.0) stop 'Error while allocating evtu in principal'
      
   evtu(1:nel*3:3)=e(1,1:nel)
   evtu(2:nel*3:3)=e(2,1:nel)
   evtu(3:nel*3:3)=e(3,1:nel)
   call cell2node(nver, mm, evtu, evtun)
   call writeVTU(nel,nver,mm,z,'tetra',evtun,'Electric field (V/m)',&
                  'vector','node',trim(fichgradsol)//'.vtu')
     
   deallocate(evtu,STAT=istat)
   if (istat.ne.0) stop 'Error while deallocating in principal' 
   deallocate(sol,STAT=istat)
   if (istat.ne.0) stop 'Error while deallocating in principal' 
   deallocate(e,STAT=istat)
   if (istat.ne.0) stop 'Error while deallocating in principal' 
   
   stop 'End of the execution'

   !end
   
   
   !  YOUR CODE HERE End

      return

   end subroutine elecx   
   

end module me

 

there is no Error  and everything works right but when  I run my program I got this Run time errors:

principal.jpg
so what's the reason?

regards

0 Kudos
gib
New Contributor II
950 Views

It's telling you that there was a read error at line 46 of felec.f90.  Since you don't provide the code for felec.f90, there's no way for anybody here to know what caused the error.

0 Kudos
John_C_
Beginner
950 Views
This Fortran codes work properly in console applications but whenever we want to make DLL and use them in c#.NET those errors appear.
0 Kudos
Lorri_M_Intel
Employee
950 Views

Is it reading from the console?

Console applications have a console (obviously) but not so obvious is the fact that DLLs do *not* have a console by default.

You can use AllocConsole to create one, which may or may not be the right thing for your application.  By that I mean, depending on what is being READ, then maybe the answer is to use a file for this case?   We can't know.

                                   --Lorri

0 Kudos
John_C_
Beginner
950 Views
My problem is with the structure of my FORTRAN file codes.I only replaced my codes instead of above uploaded project.and this is my main .f90 file of my project.so I am searching for the solution. Any help will be appreciated. Best regards
0 Kudos
Lorri_M_Intel
Employee
888 Views

John -

    I found your "endat3d" program in a previous reply, and yes, it clearly reads from the console.

     In the DLL you do not have a console, unless you have created it, and that is why you are getting the error.

     Perhaps you should always call readxml, and not call endat3d.

 

 

0 Kudos
John_C_
Beginner
888 Views
Hi, My problem solved when I start the program manually from windows it works right But when I Start from Visual Studio the console dose not show Print only Get parameters.So what is the solution? Reagrds
0 Kudos
Reply