2017-01-23 123 views
1

我想動態加載一個Fortran dll並將字符串從fortran傳回C#。在fortran代碼中一切看起來都很好,但是當返回到C#時,字符串的值將丟失。相反,在C#中設置的初始值返回。我試圖使用'ref'關鍵字來獲取通過引用傳遞的字符串,但隨後出現如下所示的錯誤。我究竟做錯了什麼?從Fortran dll傳遞字符串到C#

運行時遇到致命錯誤。錯誤的地址是0x709ce248,線程0x2ac4。錯誤代碼是0xc0000005。此錯誤可能是CLR中的錯誤,也可能是用戶代碼中不安全或不可驗證的部分。此錯誤的常見來源包括COM-interop或PInvoke的用戶編組錯誤,這可能會破壞堆棧。

Fortran代碼:

module FortLibInterface 
implicit none 

integer, parameter :: STR_LENGTH = 256 

contains 

subroutine GetString(Str) 
    !DIR$ ATTRIBUTES DLLEXPORT::GetString 
    !DIR$ ATTRIBUTES ALIAS: 'GetString' :: GetString 
    !DIR$ ATTRIBUTES REFERENCE:: Str 

    character(len=STR_LENGTH), intent(inout) :: Str 

    Str = 'bcdef...' 

end subroutine 

end module 

C#代碼:

using System; 
using System.Runtime.InteropServices; 

namespace FortranCSTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string dllPath = "C:\\Temp\\FortLib.dll"; 

      FortLibTest lib = new FortLibTest(dllPath); 

      lib.MakeTestCall(); 
     } 
    } 

    public class FortLibTest 
    { 
     public const int STR_LENGTH = 256; 

     public const string FortranFuncName = "GetString"; 

     private string pathToDll = null; 

     [DllImport("kernel32.dll", SetLastError = true)] 
     private static extern IntPtr LoadLibrary(String DllName); 

     [DllImport("kernel32.dll")] 
     private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); 

     [DllImport("kernel32.dll")] 
     private static extern bool FreeLibrary(IntPtr hModule); 

     public FortLibTest(string FullPathToDll) 
     { 
      pathToDll = FullPathToDll; 
     } 

     [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
     private delegate void TypeGetStrInfo(char[] str); 

     void GetStrInfo(char[] str) 
     { 
      IntPtr pDll = LoadLibrary(pathToDll); 
      if (pDll != IntPtr.Zero) 
      { 
       IntPtr pFunc = GetProcAddress(pDll, FortranFuncName); 
       if (pFunc != IntPtr.Zero) 
       { 
        TypeGetStrInfo func = (TypeGetStrInfo)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(TypeGetStrInfo)); 

        func(str); 
       } 
       else 
       { 
        //Something 
       } 

       FreeLibrary(pDll); 
      } 
      else 
      { 
       //Something 
      } 
     } 

     public void MakeTestCall() 
     { 
      char[] str = new char[STR_LENGTH]; 

      str[0] = 'a'; 

      GetStrInfo(str); 
     } 
    } 
} 
+0

如果直接''[DllImport(「FortLib.dll」)]'是否可以工作? – ja72

+0

是的,它的工作原理。問題是我需要動態加載它。 – JesperW

+0

呃,其實。它的工作原理是因爲我可以添加[進出]。如果我離開它,我會得到與動態調用中相同的行爲。 – JesperW

回答

0

以供將來參考。我加了[In,Out],一切正常。

[DllImport(_dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] 
public static extern void GetString([In, Out] char[] str);