Trouble with file location in excel/fortran dll connection

后端 未结 6 1852

Platform: WinXP SP2, Intel Fortran 11, Excel 2007

I\'m having trouble connecting a dll file with excel.

The dll file is relatively simple:

su         


        
6条回答
  •  星月不相逢
    2020-12-21 18:46

    Well this may be way too late, but a number of issues to consider

    1) The "calling convention" must match correctly. This has several different aspects, some of which are:

    a) The capitalisation or not or mix of s/r and Arg names.

    b) Srting calling conventions. In your code you have used some "mix" of things, and seem to be missing some bits.

    For example, try this

    subroutine FORTRANCALL (R1, NUM)        ! notice capitalisation
    !DEC$ ATTRIBUTES DLLEXPORT :: FORTRANCALL   ! notice capitalisation  and default "calling convention" (this varies between compilers)
                        ! but older CVF and Intel compilers default to CDECL, which you can set in your "properties" etc.  
                        ! Its been a while but I think newer IVF have changed to a different default convention
                        ! e.g. if you were doing this, say, in GCC/gFortran, there would be a much longer discussion
    integer, intent(in) :: r1
    Character(Len=10), intent(out) :: num   ! you might be able to use Character(Len=*) so long as its fixed on the VBA side
    !   remove this => !DEC$ ATTRIBUTES REFERENCE :: num
    
    num = ''
    write (num,'(i0)') r1 * 2
    
    return
    end subroutine FortranCall
    

    On the VBA-side, the declaration is:

    Declare Sub FortranCall_XX Lib "C:\ ... your path ...\Fcall.dll.dll" _
    Alias "FORTRANCALL" (R1 as Long, ByVal NUM As String, ByVal NumLen as Long)
    

    NOTICE the extra Arg for the String len, this only appears on the VBA side, and ONLY when String is passed ByVal (any other string passing and especially arrays of strings is a giant issue ... doable, but be prepared for some homework).

    Also, the string len here simply follows the string in terms of Arg position. However, if num was located earlier on, the the location of NumLen would be either just following the Arg num, or at the end of Arg list, depending on the calling convention.

    Also, when you create a DLL, the compiler often also creates a "Def" file. You don't need to access the Def file directly when using VBA/Fortran. However, looking inside it will show you the exact "naming style" of what the compiler thinks your s/r should be called. For example, with some calling conventions, the Def file might show the name of your s/r as something like __fortrancall@12

    ... whatever the Def files says, is what you must use in the VBA declaration Alias "__fortrancall@12"

    ... these things require a lengthy discussion for general implementation with different calling conventions/compilers.

    BTW: I added the "_XX" purely to allow the actual VBA UDF to have the "obvious name", say FortranCall, or whatever ... a reasonable habit if you will be doing a lot of this, and especially with Functions etc., but not too important here.

    and the VBA sub becomes:

    Private Sub CommandButton1_Click()
    Dim r1 As Long
    Dim num As String * 10
    Dim numlen as Long
    
     numlen = 10                ' required string len, can automate via intrinsics etc
    
     r1 = 123
     Call FortranCall_XX(r1, num, numlen)   ' notice the extra Arg
    
     TextBox1.Text = "Answer is " & num     ' you may wish to add Trim() or something in case returned num does not require 10 chars
    
    End Sub
    

    2) Do you really need to pass num as a string? Passing strings between VBA and DLL's is a big can of worms. Why not pass num as a Double or something?

    If it must be a string and if it's ByVal, then you must also include the string length as ByVal Long on the VBA-side (since in Fortran the string len is a hidden value) as shown above.

    You can pass by Ref and with/without the extra StringLen if you know how use (Cray) Pointers or Variants on the Fortran side to convert the VBString to a Fortran string etc. ... a long long discussion.

    3) A more general and "certain" way to distribute/connect to a dll is to convert the XL sheet/module to an XLA ... i.e. an Add-In. Then the XLA and DLL are (usually) put into the same Dir, and the Addin is Added to Excel via Tools/Addins etc ... which has browse to ensure the correct path.

    Then, you can also call your s/r's from any workbook/sheet etc., not just the one workbook.

提交回复
热议问题