访问冲突第二次访问C DLL函数时发生异常

本文关键字:异常 函数 DLL 第二次 访问 访问冲突 | 更新日期: 2023-09-27 18:27:14

我有以下代码:

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。这里发生了什么?

访问冲突第二次访问C DLL函数时发生异常

解决方案是在函数声明中返回的类型,而不是使用String是必需使用IntPtr

必须封送本机字符串才能在c#中使用。您的本机代码实际上并没有返回字符串对象,而是返回一个char指针。您必须告诉封送拆收器返回类型是什么,如下所示:

[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