我正在尝试动态加载Fortran DLL并将字符串从fortran传递回C#。在fortran代码中,一切看起来都很好,但是当返回C#时,字符串的值会丢失。相反,在C#中设置的初始值又回来了。我试图使用'ref'关键字来获取通过引用传递的字符串,但后来我得到如下错误。我做错了什么?
运行时遇到了致命错误。错误的地址是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 :(得分:0)
供将来参考。我添加了[In,Out],一切正常。
[DllImport(_dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void GetString([In, Out] char[] str);