Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22

Вызов структуры из импортированной DLL

28.05.2017, 19:47. Показов 3811. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть DLL:

C
1
2
3
4
5
6
7
typedef struct tagMData {
    int errCode;
    char data[256];
    int dataLength;
}MData;
//..
IMPORTDLL MData PIRITLIB_CALL libCloseDocument(unsigned char cutPaper);
Как ее правильно подключить к C#, как указать этот тип tagMData?

C#
1
[DllImport("PiritLib.dll", CallingConvention = CallingConvention.Winapi)] public static extern ... libCloseDocument(string cutPaper);
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
28.05.2017, 19:47
Ответы с готовыми решениями:

Тип const в импортированной dll
Добрый день. Есть DLL от некоего чудака. Документация говорит, что там есть такая функция: int libAddPosition(const char*...

Передача структуры из программы на c# в dll на c++ и получение структуры из dll
В общем проблема в том, что при попытке передачи структуры созданной в c# в dll на c++ происходит событие pinvokestackimbalance Гуглил...

Создание dll на C++ и вызов метода dll из C#.
Народ, может кто-нибудь выложить конкретный пример, как это сделать? Например есть же нативная библиотека bass.dll, для неё есть обёртка...

21
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,575
28.05.2017, 20:11
C#
1
2
3
4
5
6
7
8
9
10
struct tagMData
{
   public int errCode;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
   public byte[] data;
   public int dataLength;
}
 
[DllImport("PiritLib.dll", CallingConvention = CallingConvention.Winapi)]
public static extern tagMData libCloseDocument(byte cutPaper)
А еще скорее всего функция возвращает указатель, т.к. размер структуры великоват...

C#
1
2
[DllImport("PiritLib.dll", CallingConvention = CallingConvention.Winapi)]
public static extern IntPtr libCloseDocument(byte cutPaper)
1
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22
28.05.2017, 20:14  [ТС]
Добавил еще public структуре, получаю в ответ: "Сигнатура типа метода не совместима с PInvoke."
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,575
28.05.2017, 21:09
Цитата Сообщение от pistol88 Посмотреть сообщение
Добавил еще public структуре, получаю в ответ: "Сигнатура типа метода не совместима с PInvoke."
Вот поэтому я и говорю что не может он возвращать структуру целиком, там наверняка указатель на неё...
1
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22
29.05.2017, 09:45  [ТС]
При IntPtr ошибка - "ошибка чтения защищенной памяти". Судя по ответам в Гугле, проблема именно в виде структуры.

Вот самый близкий ответ, но на Java: http://www.sql.ru/forum/125271... cii-iz-dll

Буду благодарен, если кто-то поможет разобраться.
0
Эксперт .NET
 Аватар для Usaga
14308 / 9389 / 1355
Регистрация: 21.01.2016
Сообщений: 35,410
29.05.2017, 09:49
pistol88, вы уверены в этом:

C++
1
IMPORTDLL MData PIRITLIB_CALL libCloseDocument(unsigned char cutPaper);
?

Может функция всё-таки возвращает указатель? Как данная функция используется в неуправляемом коде? Можете её вызвать из простого приложения на Си\С++ и убедиться, что всё так, как вы думаете?
1
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22
29.05.2017, 10:02  [ТС]
Файл .h шел вместе с бибиотекой. Однако, если гуглить, - все плюются на разработчиков этой DLL - в документации одно, в примерах другое, по факту вообще третье. Разработка ведется только методом тыка.

Попробую поиграться с Си\С++, спасибо за совет.
0
Эксперт .NET
 Аватар для Usaga
14308 / 9389 / 1355
Регистрация: 21.01.2016
Сообщений: 35,410
29.05.2017, 10:07
pistol88, по этой ссылке есть пример использования данной либы. Посмотрите, может оно поможет чем.
1
139 / 139 / 53
Регистрация: 14.06.2016
Сообщений: 467
29.05.2017, 13:49
cdecl соглашение, а не stdcall

Добавлено через 2 минуты
Цитата Сообщение от Someone007 Посмотреть сообщение
А еще скорее всего функция возвращает указатель, т.к. размер структуры великоват...
вернуть можно хоть структуру размером в гигабайт, никто не ограничивает
1
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22
29.05.2017, 17:37  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
pistol88, по этой ссылке есть пример использования данной либы. Посмотрите, может оно поможет чем.
К сожалению, это старая версия, там все int взвращает. Нужна версия именно с поддержкой ФЗ-54, а там уже появились эти MData.

Цитата Сообщение от jr_ Посмотреть сообщение
cdecl соглашение, а не stdcall
Та же ошибка: "Сигнатура типа метода не совместима с PInvoke".
Я со своим уровнем пока не понимаю, что за "грязь" происходит в структуре на Java: http://www.sql.ru/forum/actual... g=20281795
0
Эксперт .NET
 Аватар для Usaga
14308 / 9389 / 1355
Регистрация: 21.01.2016
Сообщений: 35,410
29.05.2017, 17:53
pistol88, вызовите уже этот метод из кода на Си, да станет ясно что там да как.
0
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22
29.05.2017, 18:02  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
pistol88, вызовите уже этот метод из кода на Си, да станет ясно что там да как.
Для меня пока что это церемониальный процесс, который займет 2 дня Постепенно занимаюсь этим.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,575
29.05.2017, 18:52
Цитата Сообщение от pistol88 Посмотреть сообщение
При IntPtr ошибка - "ошибка чтения защищенной памяти"
Код покажите как использовали указатель...

Декомпилятор вообще показывает вот такую сигнатуру функции
C++
1
2
3
4
5
6
7
8
void *__cdecl libCloseDocument(void *a1, char a2)
{
  char v3; // [sp+8h] [bp-108h]@1
 
  sub_10001EF0((int)&unk_100252F8, 0);
  qmemcpy(a1, sub_10003450(&unk_100252F8, (int *)&v3, 49, a2), 0x108u);
  return a1;
}
почему-то 2 аргумента вместо одного... И как я уже говорил тут возвращается указатель на что-то размером 0x108 байт, что вполне соответствует вашей структуре...
0
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22
29.05.2017, 19:00  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
Код покажите как использовали указатель...
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        [DllImport("PiritLib.dll", CallingConvention = CallingConvention.Winapi)] public static extern int openPort(string fileName, int speed);
        [DllImport("PiritLib.dll")] public static extern int scrollPaper();
        [DllImport("PiritLib.dll")] public static extern int closePort();
        [DllImport("PiritLib.dll", CallingConvention = CallingConvention.Winapi)] public static extern int libOpenDocument(int type, int numDepart, string nameCashier, int docNumber);
        [DllImport("PiritLib.dll", CallingConvention = CallingConvention.Winapi)] public static extern int libPrintString(string textStr, string attribute);
        [DllImport("PiritLib.dll", CallingConvention = CallingConvention.Winapi)] public static extern IntPtr libCloseDocument(sbyte cutPaper);
 
        private void button1_Click(object sender, EventArgs e)
        {
 
            int result = openPort("COM5", 57600); //Замечательно
            libOpenDocument(1, 0, "Cashier1", 1); //Замечательно
            libPrintString("text", null); //Замечательно
            libCloseDocument(0); //Fail System.AccessViolationException: "Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена."
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,575
29.05.2017, 19:03
Ну как минимум CallingConvention не верный был, там везде Cdecl...

Например декомпиляция libOpenDocument

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
signed int __cdecl libOpenDocument(unsigned __int8 a1, unsigned __int8 a2, int a3, int a4)
{
  signed int v5; // [sp+0h] [bp-4h]@1
 
  sub_10001930(&unk_100252F8, 48);
  sub_10001B70((int)&unk_100252F8, a1);
  sub_10001B70((int)&unk_100252F8, a2);
  sub_10001C60(a3);
  sub_10001C10(a4);
  sub_10001D80((int)&unk_100252F8);
  v5 = sub_10002D40(&unk_100252F8);
  if ( !v5 )
  {
    if ( a1 & 0x10 )
      sub_10001EF0((int)&unk_100252F8, 1);
    v5 = sub_10002DF0(&unk_100252F8);
  }
  return v5;
}
Так пробуйте...

C#
1
2
[DllImport("PiritLib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr libCloseDocument(ref MData data, byte cutPaper);
Или так...

C#
1
2
[DllImport("PiritLib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr libCloseDocument(byte cutPaper);
Через указатель потом можно получить структуру, если она нужна...
0
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22
29.05.2017, 19:04  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
pistol88, по этой ссылке есть пример использования данной либы. Посмотрите, может оно поможет чем.
Здесь к PiritLib.dll идет еще некий PiritLibWrap.dll, который ВизуалСтудио не видит (хотя он есть и лежит рядом). В примере обращение идет именно через враппер и в примере ожидается, что вернется int. Может быть, мне этот врап поможет? Как его запустить? У меня была ошибка "не найдено", когда dll не могла подгрузить некоторые зависимости, но как посмотреть зависимости - не знаю.
0
Эксперт .NET
 Аватар для Usaga
14308 / 9389 / 1355
Регистрация: 21.01.2016
Сообщений: 35,410
29.05.2017, 19:04
pistol88, есть предположение, что libOpenDocument возврящает некий handler, указывающий на некий буфер в памяти. Этот handler нужно передать в libCloseDocument. Сообщение об ошибке недвусмысленно намекает, что функция libCloseDocument попыталась что-то откуда-то прочитать (явно полученный аргумент трактовался как указатель на что-то).

Рекомендую почитать документацию на всё это.
0
 Аватар для pistol88
0 / 0 / 1
Регистрация: 20.05.2017
Сообщений: 22
29.05.2017, 19:14  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
Так пробуйте...
C#
1
2
            MData test = new MData();
            libCloseDocument(ref test, 0);
Помощник по отладке управляемого кода "PInvokeStackImbalance" : "Вызов функции PInvoke "DvizhSeller!DvizhSeller.CashierForm::li bCloseDocument" разбалансировал стек. Вероятно, это вызвано тем, что управляемая сигнатура PInvoke не совпадает с неуправляемой целевой сигнатурой
Цитата Сообщение от Someone007 Посмотреть сообщение
Или так...
"Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена."
Цитата Сообщение от Usaga Посмотреть сообщение
libOpenDocument возврящает некий handler
Он возвращает int: 0 или номер ошибки.

Цитата Сообщение от Usaga Посмотреть сообщение
Рекомендую почитать документацию на всё это.
Читал внимательно. Не хватает знаний, чтобы вот только с этим mData разобраться. В примере на C# используется некий врап, который мой ВС не видит.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,575
29.05.2017, 19:15
Лучший ответ Сообщение было отмечено pistol88 как решение

Решение

Кстати, я возможно не прав насчет Cdecl, т.к. на версии piritlib.dll 1.0.5.0 был Cdecl, а на версии 1.0.9.744 уже Stdcall, они там реально наркоманы какие-то... Меняют API как перчатки...

И сами функции изменились немного...

Добавлено через 1 минуту
Цитата Сообщение от pistol88 Посмотреть сообщение
Помощник по отладке управляемого кода "PInvokeStackImbalance" : "Вызов функции PInvoke "DvizhSeller!DvizhSeller.CashierForm::li bCloseDocument" разбалансировал стек. Вероятно, это вызвано тем, что управляемая сигнатура PInvoke не совпадает с неуправляемой целевой сигнатурой
Пробуйте с Stdcall вместо Cdecl, т.к. см выше...
1
Эксперт .NET
 Аватар для Usaga
14308 / 9389 / 1355
Регистрация: 21.01.2016
Сообщений: 35,410
29.05.2017, 19:16
Цитата Сообщение от pistol88 Посмотреть сообщение
В примере на C# используется некий врап, который мой ВС не видит.
Какой враппер? DLL? Так подключите его к проекту: Проект -> Добавить ссылку -> Выбрать DLL.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.05.2017, 19:16
Помогаю со студенческими работами здесь

Вызов функции из dll
Добрый вечер. Написал на C# dll'ку, в которой данная функция для расчета параметров. public class Class1 { ...

Вызов кода из dll
Всем привет! Подскажите как сделать так чтобы какой то определенный код например для кнопки работал (вызывался) из dll?? Заранее спасибо!)

Вызов метода из dll
Здравствуйте. Имеется dll, в котором определен класс Class1 и метод Method1. Нужно вызвать Method1 с использованием Assembly...

Вызов из c# метода в Dll с++
Доброго времени суток, нужна помощь имеется ДЛЛ написанная на с++ И мои труды написанные на C#.В длл есть функция: PHP код: void...

Вызов функции из DLL
Всем привет! Есть такая функция в DLL: IMPORTDLL int PIRITLIB_CALL openPort(char *fileName, long speed); Я ее подключаю в C# и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru