2017-01-23 9 views
1

私はFortran dllを動的にロードし、FortranからC#に文字列を戻そうとしています。 Fortranコードの中ではすべてがうまく見えますが、C#に戻ったときに文字列の値が失われます。代わりに、C#で設定された初期値が戻ってきます。私は 'ref'キーワードを使用して文字列を参照渡しにしようとしましたが、以下のようなエラーが発生します。私は間違って何をしていますか?Fortran dllからC#に文字列を渡す

実行時に致命的なエラーが発生しました。エラーのアドレスは、スレッド0x2ac4の0x709ce248にありました。エラーコードは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

さて、実際は。私は[in、out]を追加することができるので動作します。私がそれを残しておけば、私はダイナミックコールと同じ動作をします。 – JesperW

答えて

0

。私は[In、Out]を付け加えました。

[DllImport(_dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] 
public static extern void GetString([In, Out] char[] str); 
関連する問題