我想打电话给一个传统dll编制从FORTRAN代码。我是新来的互操作的,但是我读过的一些条款在它和它看起来像我的情况应该是相当直截了当的。

这方法我真的想要呼吁有一个复杂的方法的签名,但我甚至不能叫这个简单的GetVersion方法没有得到保护记忆的违反。

这是我的DllImport码:

[DllImport("GeoConvert.dll", 
            EntryPoint="_get_version@4", 
            CallingConvention=CallingConvention.StdCall)]
public static extern void GetGeoConvertVersion([MarshalAs(UnmanagedType.LPStr, SizeConst=8)]
                                                    ref string version);

这里的FORTRAN码:

SUBROUTINE GetVer( VRSION )
C
!MS$DEFINE  MSDLL 
!MS$IF DEFINED (MSDLL)
        ENTRY Get_Version (VRSION)  
      !MS$ATTRIBUTES DLLEXPORT,STDCALL :: Get_Version
      !MS$ATTRIBUTES REFERENCE :: VRSION
!MS$ENDIF
!MS$UNDEFINE  MSDLL 
C
  CHARACTER*8  VRSION
C
  VRSION = '1.0a_FhC'                                        
C
  RETURN
  END

这是我的单元的测试,失败:

[Test]
public void TestGetVersion()
{
    string version = "";
    LatLonUtils.GetGeoConvertVersion(ref version);
    StringAssert.IsNonEmpty(version);
}

这里是错误消息我会得到:

System.AccessViolationException
Message: Attempted to read or write protected memory. 
         This is often an indication that other memory is corrupt.

其他的事情我已经试过:

  • 使用的默认编组
  • 通过char[],而不是一串(获得签名方法的错误,而不是)
有帮助吗?

解决方案 2

好吧,我得到了它的工作,该问题是通过参考。我不知道为什么,但这一工作:

[DllImport("GeoConvert.dll", 
                EntryPoint="_get_version@4", 
                CallingConvention=CallingConvention.StdCall)]
    public static extern void GetGeoConvertVersion([MarshalAs(UnmanagedType.LPArray)]
                                                    byte[] version);

与此试验:

[Test]
    public void TestGetVersion()
    {
        //string version = "";
        byte[] version = new byte[8];
        LatLonUtils.GetGeoConvertVersion(version);
        char[] versionChars = System.Text.Encoding.ASCII.GetChars(version);

        string versionString = new string(versionChars);
    }

其他提示

...剪断...好吧,我得到了它的工作,该问题是通过参考。我不知道为什么,但这一工作:...剪断...

你需要通行证的参考,因为这是语义正在使用的FORTRAN代码。客户代码是通过在一个缓冲区,FORTRAN码是要写信给以代替使用返回的价值。

...剪断...!MS$属性参考::VRSION ...剪断...

这一属性,在你的FORTRAN码规定,这种参数是通过参考。这意味着FORTRAN码要写这个地址。如果DllImport不宣布它作为一个参考价值此外,你会得到一个访问冲突。

你有没有尝试采用一个StringBuilder?

创建你的串为StringBuilder和通过,成dll功能。

Im不能确定什么Marashlling发言的使用,perhapse的默认可能的工作。

看看: 元帅C++"string"类C#P/调用

这是一篇好文章的可能的帮助,以及: 互操作的编组

我不能试试这个解决方案,因为我没有FORTRAN编译器,但我认为这会为你工作:

    [DllImport("GeoConvert.dll", 
            EntryPoint="_get_version@4", 
            CallingConvention=CallingConvention.StdCall,
            CharSet=CharSet.Ansi)]
    public static extern void GetGeoConvertVersion(StringBuilder version);

谢谢你所有的家伙,我一直试图通过一个字符串c#有一个子程序,从fortran dll,这种方法是只工作一个在很多其他人

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top