Reputation: 926
I have the following code:
class Generic
{
[DllImport("Generic.dll", EntryPoint = "Consult", CallingConvention = CallingConvention.Winapi)]
public static extern String Consulta(int NumeroSecao);
}
And
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:
__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
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
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