Правильное использование P/Invoke
Вопрос
Мне нужно вызвать внешнюю dll из С#.Это определение заголовка:
enum WatchMode {
WATCH_MODE_SYSTEM = 0,
WATCH_MODE_APPLICATION = 1 };
LONG ADS_API WDT_GetMode ( LONG i_hHandle, WatchMode * o_pWatchMode );
Я добавил перечисление и вызов на C#:
public enum WatchMode
{
WATCH_MODE_SYSTEM = 0,
WATCH_MODE_APPLICATION = 1
}
[DllImport("AdsWatchdog.dll")]
internal static extern long WDT_GetMode(long hHandle, ref WatchMode watchmode);
Это создает исключение AccessViolationException.Я знаю, что dll «работает», потому что я также добавил вызов GetHandle
который возвращает hHandle
упомянутое выше.Я попытался изменить параметр на int
(ref int watchmode
), но получаю ту же ошибку.Кто-нибудь знает, как я могу вызвать вышеуказанный вызов?
Решение
Вы столкнулись с проблемой разницы в размере параметров между C# и C++.В мире C++/Windows LONG — это 4-байтовое целое число со знаком.В мире C# long — это 8-байтовое целое число со знаком.Вам следует изменить свою подпись С#, чтобы она принимала int.
ffpf ошибается, говоря, что здесь следует использовать IntPtr.Это решит эту конкретную проблему на 32-битной машине, поскольку IntPtr будет маршалироваться как int.Если вы запустите это на 64-битной машине, оно снова будет маршалировано как 8-байтовое целое число со знаком и произойдет сбой.
Другие советы
Группа управляемого, собственного и COM-взаимодействия выпустила PInvoke Interop Assistant на codeplex.Возможно, он сможет создать правильную подпись.http://www.codeplex.com/clrinterop/Release/ProjectReleases.aspx?ReleaseId=14120