第二次访问访问C DLL函数时出现Access Violation Exception
Access Violation Exception accessing C DLL function by the second access
我有以下代码:
Generic.cs
class Generic
{
[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
public static extern String Consulta(int NumeroSecao);
}
和
main.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
Random rnd = new Random();
int random = rnd.Next(9999);
Stopwatch sw = new Stopwatch();
sw.Start();
String teste = Generic.Consult(random);
sw.Stop();
TextoLog = "Tempo de Execução:"+sw.Elapsed.Milliseconds+"ms | ConsultarSAT";
tempoEntreComandos();
}
DLL代码为:
Generic.c
__declspec(dllexport) char* __stdcall Consult(int numeroSessao)
{
memset(pcReturn,0,sizeof(char) * BUFFER_SIZE);
HANDLE fileHandle;
Communicate(&fileHandle, pcReturn,10);
return pcReturn;
}
当我第二次调用函数Consult
时出现问题,收到的消息是Access Violation Exception
。这里发生了什么?
解决方法是函数声明中的return的类型,而不是String
,必须使用IntPtr
.
必须对本机字符串进行封送处理才能在 C# 中使用。您的本机代码实际上并不是 returning 一个字符串对象,而是一个 char 指针。您必须告诉封送拆收器 return 类型是什么,如下所示:
[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern String Consulta(int NumeroSecao);
对 ASCII 字符串使用 LPStr,对 unicode 使用 LPWStr。
实际上,手动编组字符串可能是更好的主意,因为编组器会在转换后立即释放本机字符串。声明将是
[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
public static extern IntPtr Consulta(int NumeroSecao);
然后您像这样手动将 IntPtr 编组为字符串
String str = Marshal.PtrToStringAnsi(strptr); // for ansi
String str = Marshal.PtrToStringUni(strptr); // for unicode
我有以下代码:
Generic.cs
class Generic
{
[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
public static extern String Consulta(int NumeroSecao);
}
和
main.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
Random rnd = new Random();
int random = rnd.Next(9999);
Stopwatch sw = new Stopwatch();
sw.Start();
String teste = Generic.Consult(random);
sw.Stop();
TextoLog = "Tempo de Execução:"+sw.Elapsed.Milliseconds+"ms | ConsultarSAT";
tempoEntreComandos();
}
DLL代码为:
Generic.c
__declspec(dllexport) char* __stdcall Consult(int numeroSessao)
{
memset(pcReturn,0,sizeof(char) * BUFFER_SIZE);
HANDLE fileHandle;
Communicate(&fileHandle, pcReturn,10);
return pcReturn;
}
当我第二次调用函数Consult
时出现问题,收到的消息是Access Violation Exception
。这里发生了什么?
解决方法是函数声明中的return的类型,而不是String
,必须使用IntPtr
.
必须对本机字符串进行封送处理才能在 C# 中使用。您的本机代码实际上并不是 returning 一个字符串对象,而是一个 char 指针。您必须告诉封送拆收器 return 类型是什么,如下所示:
[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern String Consulta(int NumeroSecao);
对 ASCII 字符串使用 LPStr,对 unicode 使用 LPWStr。
实际上,手动编组字符串可能是更好的主意,因为编组器会在转换后立即释放本机字符串。声明将是
[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
public static extern IntPtr Consulta(int NumeroSecao);
然后您像这样手动将 IntPtr 编组为字符串
String str = Marshal.PtrToStringAnsi(strptr); // for ansi
String str = Marshal.PtrToStringUni(strptr); // for unicode