Juliano Oliveira
Juliano Oliveira

Reputation: 926

Access Violation Exception accessing C DLL function by the second access

I have the following code:

Generic.cs

class Generic
{
    [DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
    public static extern String Consulta(int NumeroSecao);       
}

And

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();
}

The code of DLL is:

Generic.c

__declspec(dllexport) char* __stdcall Consult(int numeroSessao)
{
    memset(pcReturn,0,sizeof(char) * BUFFER_SIZE);
    HANDLE fileHandle;
    Communicate(&fileHandle, pcReturn,10);
    return pcReturn;
}

The problem occurs when I call function Consult the second time, the message received is an Access Violation Exception. What is happening here?

Upvotes: 0

Views: 332

Answers (2)

Sebastian Grzeda
Sebastian Grzeda

Reputation: 11

Native strings have to be marshaled to be used in c#. Your native code is not actually returning a string object, but a char pointer. You have to tell the marshaler what the return type is, as so:

[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern String Consulta(int NumeroSecao);

Using LPStr for ASCII strings and LPWStr for unicode.


Actually it might be a better idea to marshal the string manually as the marshaler deallocates the native string right after conversion. The declaration would be then

[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
public static extern IntPtr Consulta(int NumeroSecao);

And you manually marshal the IntPtr to string like so

String str = Marshal.PtrToStringAnsi(strptr); // for ansi
String str = Marshal.PtrToStringUni(strptr); // for unicode

Upvotes: 1

Juliano Oliveira
Juliano Oliveira

Reputation: 926

The solution is the type for the return in the declaration of function, instead of use String is necessary use of IntPtr.

Upvotes: 1

Related Questions