У меня возникли некоторые трудности с вызовом P / Invoke на C ++ DLL. Я получаю сообщение об ошибке «невозможно найти точку входа».
В C ++ я выставляю функцию так …
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport)
long
WINAPI
MgScSCardUIDlgSelectCardW(__inout LPOPENCARDNAMEW_EX pOcne);
#ifdef __cplusplus
}
#endif
Инструкция dllimport в C # выглядит следующим образом:
[DllImport("mgsc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 MgScSCardUIDlgSelectCardW([MarshalAs(UnmanagedType.Struct)] [In, Out] ModWinsCard.OPENCARDNAME_EX ocnwex);
Я пробовал это без соглашения о вызовах, стандарта и соглашения о вызовах winapi. Тот же результат со всеми. Я посмотрел на открытые функции с DependencyWalker и увидел, что они выставлены как «_MgScSCardUIDlgSelectCardW @ 4». Я понимаю, что декорация нормальная (но это объявление ‘extern «C»‘ должно было обрабатывать это ??), но я никогда не видел ни одного примера кода, в котором функция dllimport имела бы функцию, выглядящую таким образом, поэтому это не выглядит так, как будто Вот как я должен это называть.
Здесь я видел ответы, рекомендующие файлы .def, но я бы предпочел не иметь с этим дело, поскольку это еще одна вещь, которую я должен выучить и облажать, когда мне просто нужно сделать это.
Все нормально с DLL. Вы получаете преимущество постфикса @ 4, добавленного к имени компилятором. Он описывает размер значений аргументов, передаваемых функции, 4 байта для структурного указателя. Это ловит ошибки в объявлении функции в коде клиента, такие несоответствия могут быть очень трудно устранить неполадки, потому что они дисбаланс стека.
Что и здесь хорошо работает, вы почти наверняка объявили, что функция неправильная. 99% вероятности, что вы объявили OPENCARDNAME_EX как структуру, а не как класс. Что требует, чтобы вы передали аргумент по ссылке, а не по значению. Атрибут [MarshalAs] тоже неверен. Fix:
[DllImport("mgsc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern Int32 MgScSCardUIDlgSelectCardW(ref ModWinsCard.OPENCARDNAME_EX ocnwex);
Других решений пока нет …