.NET Interop IntPtr vs. ref
Prawdopodobnie pytanie noob, ale interop nie jest jeszcze jedną z moich mocnych stron.
Czy poza ograniczeniem liczby przeciążeń powinienem zadeklarować moje DllImports jak:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
I używaj ich w ten sposób:
IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(formatrange));
Marshal.StructureToPtr(formatrange, lParam, false);
int returnValue = User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_FORMATRANGE, wParam, lParam);
Marshal.FreeCoTaskMem(lParam);
Zamiast tworzyć ukierunkowane przeciążenie:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref FORMATRANGE lParam);
I używając tego jak:
FORMATRANGE lParam = new FORMATRANGE();
int returnValue = User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_FORMATRANGE, wParam, ref lParam);
Przeciążenie przez ref staje się łatwiejsze w użyciu, ale zastanawiam się, czy jest wada, o której nie wiem.
Edytować:
Jak dotąd mnóstwo świetnych informacji.
@P Daddy: Czy masz przykład bazowania klasy struct z abstrakcyjnej (lub dowolnej) klasy? Zmieniłem swój podpis na:
[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, [In, Out, MarshalAs(UnmanagedType.LPStruct)] CHARFORMAT2 lParam);
BezIn
, Out
, iMarshalAs
SendMessage (EM_GETCHARFORMAT w moim teście) kończy się niepowodzeniem. Powyższy przykład działa dobrze, ale jeśli zmienię go na:
[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, [In, Out, MarshalAs(UnmanagedType.LPStruct)] NativeStruct lParam);
Otrzymuję wyjątek System.TypeLoadException, który mówi, że format CHARFORMAT2 jest nieprawidłowy (spróbuję przechwycić go tutaj).
Wyjątek:
Nie można załadować typu „CC.Utilities.WindowsApi.CHARFORMAT2” z zespołu „CC.Utilities, Version = 1.0.9.1212, Culture = neutral, PublicKeyToken = 111aac7a42f7965e”, ponieważ format jest nieprawidłowy.
Klasa NativeStruct:
public class NativeStruct
{
}
próbowałemabstract
, dodającStructLayout
atrybut itp. i otrzymuję ten sam wyjątek.
[StructLayout(LayoutKind.Sequential)]
public class CHARFORMAT2: NativeStruct
{
...
}
Edytować:
Nie śledziłem FAQ i zadałem pytanie, które można omówić, ale nie otrzymałem pozytywnej odpowiedzi. Oprócz tego w tym wątku było wiele wnikliwych informacji. Więc pozostawiam czytelnikom głosowanie nad odpowiedzią. Najpierw będzie odpowiedź od 1 do ponad 10 głosów w górę. Jeśli żadna odpowiedź nie spełni tego w ciągu dwóch dni (12/17 PST), dodam własną odpowiedź, która podsumowuje całą pyszną wiedzę w wątku :-)
Edytuj ponownie:
Skłamałem, akceptując odpowiedź P Daddy, ponieważ jest on mężczyzną i był wielką pomocą (ma też uroczą małpkę :-P)