Правильный вызов сложной подпрограммы / функции Fortran из Mono C # - PullRequest
0 голосов
/ 18 июня 2019

У меня есть приложение C # (Unity / Mono на MacOS), где мне нужно решить типичную задачу оптимизации матрицы Ax = b с размерами 3xN. Подробнее здесь . Я обнаружил, что основной метод для этого называется неотрицательными наименьшими квадратами (NNLS) и искал чистую реализацию C # (или аналогичную), но безуспешно.

Любые решения приветствуются, но самое близкое, что я пришел, это реализация Fortran , используемая функцией SciPy nnls () с заголовком fortran:

      SUBROUTINE NNLS (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE)
C     ------------------------------------------------------------------

      ! Don't leave the calling convention to chance.
      !GCC$ ATTRIBUTES CDECL ::  NNLS

      !DIR$ ATTRIBUTES DLLEXPORT :: NNLS
      !DIR$ ATTRIBUTES ALIAS: 'NNLS' :: NNLS

      integer I, II, IP, ITER, ITMAX, IZ, IZ1, IZ2, IZMAX, J, JJ, JZ, L
      integer M, MDA, MODE,N, NPP1, NSETP, RTNKEY
c     integer INDEX(N)  
c     double precision A(MDA,N), B(M), W(N), X(N), ZZ(M)   
      integer INDEX(*)  
      double precision A(MDA,*), B(*), W(*), X(*), ZZ(*)   
      double precision ALPHA, ASAVE, CC, DIFF, DUMMY, FACTOR, RNORM
      double precision SM, SS, T, TEMP, TWO, UNORM, UP, WMAX
      double precision ZERO, ZTEST
      parameter(FACTOR = 0.01d0)
      parameter(TWO = 2.0d0, ZERO = 0.0d0)
C     ------------------------------------------------------------------

....

Следуя нескольким руководствам, я успешно скомпилировал это с помощью gfortran (с несколькими предупреждениями) для библиотеки .so (эквивалент Mac DLL) и пытался загрузить ее в C # для вызова.

// C# alias function
[DllImport("Fortran/NNLS.so", CallingConvention = CallingConvention.Cdecl)]
public static extern int NNLS(ref float[,] A, ref int MDA, ref int M, ref int N, ref float[] B, out float[] X, out float RNORM, ref float[] W, ref float[] ZZ, ref int[] INDEX, out int MODE);

// C# call
NNLS(ref A, ref mda, ref m, ref n, ref b, out x, out rnorm, ref w, ref zz, ref index, out mode);

Импорт DLL работает нормально, но выдает EntryPointNotFoundException: NNLS. Я перепробовал ряд изменений в именах, связывании, соглашениях о вызовах и т. Д. Что я делаю не так?

Единственное, о чем я могу думать, это то, что в настоящее время в верхней части файла fortran нет объявления модуля / интерфейса, так как это приводит к сбою компилятора, хотя и не знаю, как это решить.

...