#c# #dllimport
#c# #dllimport
Вопрос:
У меня есть некоторый код на C, который компилируется в DLL. Из C # мне нужно передать ему массив целых чисел, и мне нужно получить из него массив целых чисел.
Вот что у меня есть на данный момент. В C # единственная функция, которая работает, — это bar(). Он возвращает 22 и записывает в файл, как и ожидалось. Другие записывают данные в свои файлы должным образом, но выдают исключение, когда управление возвращается C #. Он читает,
«Вызов функции PInvoke ‘irhax!irhax.App::foo’ привел к дисбалансу стека. Вероятно, это связано с тем, что управляемая подпись PInvoke не соответствует неуправляемой целевой подписи. Убедитесь, что соглашение о вызове и параметры подписи PInvoke соответствуют целевой неуправляемой подписи.»
C (библиотека DLL):
#define IG_API __declspec(dllexport)
IG_API void foo(int i) {
FILE *f = fopen("foo.txt", "a ");
fprintf(f, "%dn", i);
fclose(f);
}
IG_API int bar(void) {
FILE *f = fopen("bar.txt", "a ");
fprintf(f, "bar!n");
fclose(f);
return 22;
}
IG_API void transmitIR(unsigned *data, int length) {
FILE *f = fopen("transmit.txt", "a ");
for(int i = 0; i < length; i)
fprintf(f, "%d, ", data[i]);
fprintf(f, "n");
fclose(f);
}
IG_API int receiveIR(unsigned *data, int length) {
for(int i = 0; i < length; i)
data[i] = 4;
return length;
}
C # (вызывающий объект):
[DllImport("Plugin.dll")]
static extern void foo(int i);
[DllImport("Plugin.dll")]
static extern int bar();
[DllImport("Plugin.dll")]
static extern void transmitIR(uint[] data, int length);
[DllImport("Plugin.dll")]
static extern int receiveIR(out uint[] data, int length);
Я в растерянности. Что я делаю не так? Поскольку я даже не могу заставить foo (int) работать, это кажется хорошим местом для начала.
Ответ №1:
Ваш код на C использует соглашение о вызове cdecl. Код C # использует stdcall.
Все DLLImport
атрибуты должны быть:
[DllImport("Plugin.dll", CallingConvention=CallingConvention.Cdecl)]
Конечно, вы могли бы альтернативно переключить код C на stdcall с помощью __stdcall
. Но убедитесь, что вы выполняете только одно из этих действий!
receiveIR
не требуется out
. Вы должны объявить это:
static extern int receiveIR(uint[] data, int length);
Ответ №2:
Знаете ли вы соглашение о вызове функций C? Как указано в ошибке, это, вероятно, несоответствие. Соглашение о вызове по умолчанию — stdcall, но если эти функции используют соглашение cdecl, вы, скорее всего, получите эту ошибку. Попробуйте
[DllImport("Plugin.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void foo(int i);