Functie in Fortran DLL aanroepen vanuit Excel VBA

Pagina: 1
Acties:
  • 115 views sinds 30-01-2008
  • Reageer

  • EvdB
  • Registratie: November 2001
  • Laatst online: 19-05 17:15
Ik heb met Fortran een DLL (UOMCONVERT.DLL) gemaakt met verschillende functies daarin om eenheden om te zetten. o.a de functie Length

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
FUNCTION LENGTH(L, IN, OUT)
IMPLICIT NONE
!DEC$ IF DEFINED (_DLL)
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT :: LENGTH
!DEC$ END IF

      CHARACTER*6 IN, OUT
      REAL*8 L, LENGTH
      IN(1:6) = '      '
      OUT(1:6) = '      '
IF (IN(1:6).EQ.'m     ') THEN
  IF (OUT(1:6).EQ.'mm    ') LENGTH = L * 0.001
RETURN
END FUNCTION


In Excel roep ik deze aan met het volgende in VBA:
code:
1
2
Public Declare Function LENGTH Lib "UOMCONVERT.dll" _
      (Value As Double, InputUOM As String, OutputUOM As String) As Double

Ik kreeg alleen als resultaat als ik in een cell =LENGTH(10.2,"m","mm") -> #VALUE
Wat doe ik verkeerd?

[ Voor 7% gewijzigd door EvdB op 19-11-2004 12:58 ]


  • zwippie
  • Registratie: Mei 2003
  • Niet online

zwippie

Electrons at work

Ik weet de oplossing niet, maar wil best een poging wagen:

Staat de functie declaratie in het code scherm van je werkblad of in het codescherm van je excel-document. (beetje vaag uitgelegd, maar je snapt het hopelijk wel).
Heb je bij menu 'Extra->References' je dll toegevoegd?
Misschien helpt het nog als je de functieaanroep middel Call doet, dus
cell = Call (LENGTH(10.2, "m", "mm")

Ik heb geen kaas gegeten van Fortran, dus of je code klopt weet ik niet. :)

How much can you compute with the "ultimate laptop" with 1 kg of mass and 1 liter of volume? Answer: not more than 10^51 operations per second on not more than 10^32 bits.


  • EvdB
  • Registratie: November 2001
  • Laatst online: 19-05 17:15
Ik heb de functie declaratie in een aparte module staan. Als ik in Excel dan op de functie knop f(x) in de werkbalk druk zie ik bij User Defined wel mijn functie staan.

  • JJvG
  • Registratie: Juli 2003
  • Laatst online: 27-04 16:49
is LENGTH niet een beschermd woord/commando binnen Excel?
Probeer eens de functie een alias te geven

code:
1
2
Public Declare Function LENGTH Lib "UOMCONVERT.dll" Alias "Fortran_Length"_
      (Value As Double, InputUOM As String, OutputUOM As String) As Double

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Je hoopt dat een FORTRAN CHARACTER*6 gelijk is aan een VBA String?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

MSalters schreef op zaterdag 20 november 2004 @ 00:37:
Je hoopt dat een FORTRAN CHARACTER*6 gelijk is aan een VBA String?
Dit vereist inderdaad een andere aanpak. Strings moet je inlezen in een byte-array.

  • EvdB
  • Registratie: November 2001
  • Laatst online: 19-05 17:15
Ik had zo'n vermoeden dat het te maken had met die strings. Ik kan eens proberen om het als integers or double/real te definieren. Dat gaat wat makkelijker.

Verwijderd

Ik weet ook niets van Fortran, maar ik weet wel eea van hoe VB(A) omgaat met het doorgeven van strings aan een functie die je met een declare in een DLL aanroept. Wllicht dat je hier iets aan hebt

In VB(A) zijn alle strings Unicode, wat oa wil zeggen dat er per karakter 2 bytes worden gebruikt, deze worden ook wel BSTR genoemd.

Als je van een functie in de declare hebt aangegeven dat de parameter een String is gaat VB er vanuit dat de DLL functie een C-stijl string verwacht. Dat wil zeggen een pointer naar een array met precies 1 byte per karakter plus een laatste 0-byte om het einde van de string aan te geven.

Op het moment dat je DLL functie wordt aangeroepen wordt er een nieuwe C-stijl string aangemaakt en wordt de inhoud van je VB string onder water gekopieerd (vertaald) naar een C-string. Op het moment dat de functie retourneerd wordt de C-stjl string weer terug vertaald naar de VB string voor het geval hij door de functie is veranderd..

De vraag is nu dus eigenlijk: verwacht jouw Fortran functie zoals je hem hebt gedefinieerd inderdaad een C-stijl string.

Het is heel belangrijk dat de functie signatuur van de fortran functie exact overeenkomt met de declare in VB. Op bit niveau zitten daar hier en daar wat eigenaardigheden in zoals het string voorbeeld. Er gaat ook helemaal niemand helpen als de declare niet overeenkomt met het geen de functie daadwerkelijk verwacht, als je geluk hebt gebeurd er niets, als je echt pech hebt kijg je een access violation en crached in dit geval excell.

Nogmaals, ik begrijp niets van Fortran en heb ook geen idee wat jouw functie moet doen, maar kun je hetzelfde niet ook gewoon in VBA doen? Zo ingewikkeld kan het toch niet zijn?

Verwijderd

Er kunnen een aantal dingen verkeerd lopen:

1 : Het code voorbeeld laat zien dat de FORTRAN functie STDCALL is als symbool _DLL bestaat. Wanneer dat niet het geval is weet ik niet wat het call-type wordt (fastcall ?), maar VBA snapt t dan in elk geval niet meer. Controleer dus of symbool _DLL gedefineerd was bij compilatie.

2 : STDCALL beschrijft dat c-strings als char* (pointer naar byte-array) gepasst worden. VBA-strings zijn echter geen c-strings. Om VBA-strings te passen moet je de individuele letters in een Array of Byte plaatsen en als eindemarkering een 0 plaatsen. De arrays moet je ByRef passen. Omdat de FORTRAN rekent op vaste lengte is het wel nodig alle elementen van de array netjes in te richten.

3 : Bij falen van de checks is de functie waarde niet gedefinieerd. Het type van het resultaat is een double (real*8) die via de stack teruggegeven wordt. Doubles zijn echter op een bepaalde manier opgemaakt en als de stack rommel bevat (2 maal een random int32) kan de double niet geinterpreteerd worden.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
bloog: zonder _DLL wordt de hele functie LENGTH niet eens geexporteerd.

TS: heb je al een functie TEST zonder argumenten werkend?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1