P / Invoke: C # P / Вызов функции C возвращает разные значения в зависимости от платформы (X86 против X64)? - PullRequest
0 голосов
/ 23 января 2019

Я чувствую себя нелепо, задавая этот вопрос, но у меня есть проблема, на которую я смотрю уже несколько часов, и я не могу на всю жизнь понять, что не так.

У меня есть следующая функциясигнатура, определенная в C DLL:

__declspec(dllexport) _Bool __cdecl cs_support(int query);

Я создал следующий эквивалент сигнатуры P / Invoke во внутреннем классе:

[DllImport("capstone", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool cs_support(int queryOption);

Внутренний класс определен в проекте .NET, которыйстроит 2 сборки, 1 для .NET Framework и одну для .NET Core.

Я создаю небольшое приложение командной строки .NET, которое загружает как сборку .NET, так и DLL C и вызывает функцию следующим образом:

var isSupported = NativeImport.cs_support(65503);

Теперь вот что интересно, что я не могу понять.Когда я вызываю функцию один раз, если приложение нацелено на X86, и один раз, если оно нацелено на X64 (следовательно, загружаются либо версии C86, либо X64 DLL-библиотеки C), я получаю разные значения!Что еще более странно, так это то, что версия X64 возвращает правильное значение, а версия X86 - нет!

У меня есть доступ к исходному коду C DLL, и у него нет директив процессора, чтобы возвращать разные значения для одного и того жеВвод на основе целевой платформы.Код C на самом деле очень прямолинеен и должен возвращать одно и то же значение для одного и того же ввода независимо от целевой платформы.

Кроме того, когда я создаю небольшое приложение командной строки C для тестирования, возвращаются те же правильные значениянезависимо от целевой платформы.

Таким образом, кажется, что только когда C DLL загружается из .NET и вызывается P /, я вижу такое поведение!

Итак, мой вопрос, почемуэто происходит?Есть ли какое-то странное поведение P / Invoke, из-за которого я должен был бы следить за этим?

Я работаю в Windows 10 64 Bit, если это имеет значение.

Спасибо!

1 Ответ

0 голосов
/ 24 января 2019

Из обсуждения в комментариях стало ясно, что проблема была вызвана нативной функцией, возвращающей значение _Bool, с типом _Bool, имеющим размер байта 1.

Однако по умолчанию маршаллер .NET маршаллизирует C # bool в и из типа данных Windows API BOOL, размер байта которого равен 4 (также см. Здесь ).

Чтобы правильно маршалировать однобайтовое значение _Bool, маршаллеру необходимо явно указать, чтобы маршалировать значение C # bool как один байт:

[DllImport("capstone", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
internal static extern bool cs_support(int queryOption);
...