同样调用DLL两次,使用pinvoke,得到不同的结果

时间:2016-01-14 19:38:45

标签: c# fortran pinvoke

我通过Pinvoke在C#应用程序(net45,VS2013,windows 7 64)上使用fortran DLL(使用mingw编译),我无法控制它。然而,它具有从绝对等于调用产生不同结果的奇怪行为。它比这复杂一点,请查看示例(假设' get'是ddl方法):

首先C#运行

  1. '获得'呼叫生成' 200'
  2. '获得'呼叫生成' -100'
  3. 第二次C#运行

    1. 来电制作' 200'
    2. 来电制作' -100'
    3. 正确的结果始终是第一次运行之一。我相信存在一些糟糕的内存使用情况,因为我实际上遇到了类似的问题,其中包括' get'不能第二次调用(它会崩溃)。最初我尝试为所有调用加载DLL一次,然后在每次调用之前重新加载,但两者的行为完全相同。见下文:

      为所有通话加载一次dll

      [DllImport(@"gamma.dll", CallingConvention = CallingConvention.Cdecl)]
              static extern void get_(ref GammaInputStruct inputParams, ref int nobs, float[] utmx, float[] utmy, float[] dobi, float[] embi, float[] sobi, float[] tci, float[] gamma, float[] matrixOut);
      

      在每次通话前重新加载dll (请参阅http://blogs.msdn.com/b/jmstall/archive/2007/01/06/typesafe-getprocaddress.aspx

      [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
              delegate void GetDelegate(ref GammaInputStruct inputParams, ref int nobs, float[] utmx, float[] utmy, float[] dobi, float[] embi, float[] sobi, float[] tci, float[] gamma, float[] matrixOut);
      
      using (var lib = new UnmanagedLibrary("gamma.dll"))
                  {
                      var func = lib.GetUnmanagedFunction<GetDelegate>("get_");
                      func(ref input.InputParams, ref input.Nobs, input.Utmx, input.Utmy, input.Dobi, input.Embi, input.Sobi.ToArray(), input.Tci, input.Gamma, matrixOut);
                  }
      

      最后,下面是&#34; gamma.dll&#34;编译,也是方法签名的源代码。

      Fortran编译:

      gfortran.exe -Jobj\Debug\  -ffree-line-length-none -ffixed-line-length-none -Wall -g -DBUILD_DLL -fPIC  -ffixed-form -ffree-form    -c "Gamma14.f90" -o obj\Debug\Gamma14.o
      

      Fortran获得签名:

      !DEC$ ATTRIBUTES DLLEXPORT::get
            subroutine get(inputParams,nobsIn,utmx,utmy,dobi,embi,sobi,tci,gammaArray,matrixOut)
      

      最后但并非最不重要的是,此代码在WPF GUI上运行,并由用户选择输入,因此它可以无限次地运行,具有相同或不同的输入。

      我没有想法了。拿到一些?

      谢谢!

      更新----------------

      还尝试复制(不同的名称)并在调用之间删除DLL,但没有成功。

      我对DLL /内存使用的了解是非常基本的,但我希望有一种方法可以使每个调用成为一个全新的调用,这会使代码抵抗某些fortran代码的味道。考虑到我的时间限制,尝试和修复fortran代码并不是一个选择。

      更新2 --------------

      我找到了有关该问题的更多信息,并设法解决了这个问题。我正在两个不同的DLL上进行两次pinvoke调用,这两个DLL都是fortran,具有不同且不相关的源代码。它们是管道的一部分,但是在下面的示例中,为了测试,调用彼此完全无关。让我们称他们为“DLL1&#39;和&#39; DLL2&#39;:

      • 情况1:运行&#39; DLL1&#39;多次 - &gt;行
      • 情况2:运行&#39; DLL2&#39;多次 - &gt;行
      • 情况3:运行DLL1&#39;曾经,然后是DLL2&#39;多次 - &gt; 的 BAD

      请参阅下面的答案。

1 个答案:

答案 0 :(得分:-1)

我尝试在每次调用之前重新加载'DLL1'并且它有效。我做了一些测试,发现除非我为两者做这件事,否则它将不起作用。

我仍然无法真正理解所有这一切的原因,但无论如何,这是有效的。