Ну, это может быть слишком поздно, но нужно рассмотреть ряд вопросов
1) «Соглашение о вызовах» должно соответствовать правильно. Это имеет несколько различных аспектов, некоторые из которых:
a) Прописная или нет или комбинация имен s / r и Arg.
б) Srting соглашения о вызовах. В своем коде вы использовали некоторое «сочетание» вещей и, кажется, упускаете некоторые биты.
Например, попробуйте это
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
На стороне VBA объявление:
Declare Sub FortranCall_XX Lib "C:\ ... your path ...\Fcall.dll.dll" _
Alias "FORTRANCALL" (R1 as Long, ByVal NUM As String, ByVal NumLen as Long)
ОБРАТИТЕ ВНИМАНИЕ, дополнительный Arg для строки String, это появляется только на стороне VBA, и ТОЛЬКО, когда String передается ByVal (любая другая передача строки и особенно массивы строк - гигантская проблема ... выполнима, но будьте готовы к немного домашней работы).
Кроме того, строка len здесь просто следует за строкой с точки зрения позиции Arg. Однако, если num был расположен ранее, местоположение NumLen будет либо просто следовать за Arg num, либо в конце списка Arg, в зависимости от соглашения о вызовах.
Кроме того, когда вы создаете DLL, компилятор также часто создает файл «Def». Вам не нужно напрямую обращаться к файлу Def при использовании VBA / Fortran. Однако, заглянув внутрь, вы увидите точный «стиль именования» того, что, по мнению компилятора, должен называться ваш s / r. Например, при некоторых соглашениях о вызовах файл Def может показывать имя вашего s / r как-то так:
__fortrancall @ 12
... что бы ни говорили файлы Def, это то, что вы должны использовать в объявлении VBA Alias "__fortrancall @ 12"
... эти вещи требуют длительного обсуждения для общей реализации с различными соглашениями о вызовах / компиляторами.
Кстати: я добавил «_XX» исключительно для того, чтобы фактическая UDF VBA имела «очевидное имя», скажем FortranCall, или что-то еще ... разумная привычка, если вы будете делать это много, особенно с Функции и т. Д., Но не слишком важные здесь.
и саб VBA становится:
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) Вам действительно нужно передать num в виде строки? Передача строк между VBA и DLL - это большая банка червей. Почему бы не передать num как Double или что-то еще?
Если это должна быть строка и если это ByVal, то вы также должны включить длину строки как ByVal Long на стороне VBA (поскольку в Fortran строка len является скрытым значением), как показано выше.
Вы можете пройти мимо Ref и с / без дополнительного StringLen, если вы знаете, как использовать (Cray) указатели или варианты на стороне Fortran для преобразования VBString в строку Fortran и т. Д. ... длинное долгое обсуждение.
3) Более общий и "определенный" способ распространения / подключения к dll - это преобразование листа / модуля XL в XLA ... т.е. в надстройку. Затем XLA и DLL (обычно) помещаются в один и тот же Dir, и надстройка добавляется в Excel с помощью инструментов / надстроек и т. Д., Которая позволяет просматривать правильный путь.
Затем вы также можете вызывать своих з / р из любой рабочей книги / листа и т. Д., А не только из одной рабочей книги.