对 DLL 进行两次相同的调用,使用 pinvoke,得到不同的结果

Same call on DLL twice, with pinvoke, getting different results

我在 C# 应用程序(net45、VS2013、windows 7 64)上使用我无法控制的 fort运行 DLL(用 mingw 编译),通过Pinvoke。但是,它具有从绝对相等调用中产生不同结果的 st运行ge 行为。它比这稍微复杂一点,查看示例(假设 'get' 是 ddl 方法):

第一个 C# 运行

  1. 'get' 调用产生“200”
  2. 'get' 调用产生'-100'

第二个 C# 运行

  1. get 调用产生“200”
  2. get 调用产生“-100”

正确的结果总是第一个 运行。我相信存在某种糟糕的内存使用情况,因为我实际上遇到了类似的问题,其中 '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);
            }

最后,下面是"gamma.dll"的编译过程以及方法签名的源代码。

堡运行编译:

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

要塞运行 获取签名:

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

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

我运行没主意了。拿到一些?

谢谢!

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

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

我对 DLL's/memory 用法的了解非常基础,但我希望有一种方法可以使每次调用都是全新的,这将使代码能够抵抗某些堡垒运行 代码有味道。考虑到我的时间限制,尝试并修复堡垒运行 代码并不是一个很好的选择。

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

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

请参阅下面的答案。

我尝试在每次调用前重新加载 'DLL1',它成功了。我做了一些更多的测试,发现除非我对其中的 both 都这样做,否则它不会起作用。

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