|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
Имеется оборудование, укомплектованное документацией и примером на С#. Задача его включить в проект на Delphi Проблема возникла с тем, чтобы получить результат из функции Код: plaintext 1.
сама функция объявлена как: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
где LIBCTMCLIENT_FUNC насколько я понимаю - extern "C" Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
Предположительно на Delphi это может выглядеть как Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
однако такой вариант не передает данные в библиотеку, что подтверждают логи внутреннего сервиса Варианты Код: pascal 1. 2. 3. 4. 5. 6.
отлично передают параметр в библиотеку, но вызывают сложности с получением ответа по причине того, что адрес на который указывает указатель содержит нечто не очень похожее на ответ. (ориентируюсь, что в поле error должно быть либо значение перечисления CTM_BEGIN_TRX_SUCCESS либо альтернативное из перечисления значение.) Вариант"убрать/добавить packed в record опробован. перевести функцию в процедуру с прямым набором параметров Код: pascal 1.
приводит к тому, что оборудование не получает входящий параметр (как бы сдвигает его по порядку вправо) (исследовано на другой процедуре где входящих параметров больше) Вариант обратного перечисления паремтров.. вырождается к функции с указателем... параметр в оборудование уходит, ответ... неопределен Код: pascal 1.
Линковка cdecl подтверждается декларацией этой же функции в С# Код: c# 1. 2. 3. 4. 5. 6. 7.
что отвратительно, пример на С# работает... Собственнно вопрос к знатокам... Как правильно получить содержимое или что требуется для того, чтобы эту информацию получить ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 12:41 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
maremoraCTMBeginTransactionError Вот это - просто integer. Как возвращается структура - надо гуглить. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 12:54 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
Если это 32х-разрядная dll, собранная msvc компилятором, то результат будет в eax:edx. Для C++ builder есть http://docwiki.embarcadero.com/RADStudio/Sydney/en/Msreturn А как delphi это объяснить - не знаю. Разве что сказать, что функция возвращает int64, и вручную сдвигами выделить части структуры. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 13:46 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
Barlone, Это про декларацию fastcall - у emba и ms они разные. Тут же декларация cdecl - должно работать в первоначальном варианте. Код: pascal 1. 2.
Надо смотреть, что передается в transactionId и как он принимается библиотекой? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 14:41 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
ziv-2014 Надо смотреть, что передается в transactionId и как он принимается библиотекой? туда честно передается нультерминированная строка ... хоть адресом на массив хоть Код: pascal 1. 2. 3. 4. 5. 6. 7.
судя по тому, что библиотека далее ведет себя ожидаемо (согласно логу) то со входящим параметром все нормально ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 14:47 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
Barlone .... и вручную сдвигами выделить части структуры. еще бы понять куда... сдвигать и от чего плясать.. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 15:43 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
Берёшь тестовую программу на Си, компилируешь в ассемблер, смотришь как возвращается структура. Компилируешь свою программу на Дельфи, смотришь в её ассемблер, сравниваешь. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 15:50 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
maremora, У тебя же возвращает структуру, а не указатель? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 16:59 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
ziv-2014, В том и вопрос, что по доке - структуру, причем по значению. А вот "по-делфийски" - любое упоминание структуры в декларации функции/процедуры на первом месте убивает в хлам передачу параметров функции в библиотеку. в С# примере - все прекрасно, но там явно об этом побеспокоился компоновщик самого шарпа.. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 17:07 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
maremora, Быть такого не может, я еще пойму, что есть проблемы с возвратом результата функции. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 19:11 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
maremoraА вот "по-делфийски" - любое упоминание структуры в декларации функции/процедуры на первом месте убивает в хлам передачу параметров функции в библиотеку. Для особо ленивых: https://stackoverflow.com/questions/24741218/how-c-compiler-treats-a-struct-return-value-from-a-function-in-asm http://docwiki.embarcadero.com/RADStudio/Sydney/en/Program_Control_(Delphi)#Handling_Function_Results Для ещё более ленивых: обломись, никак ты эту структуру не получишь. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 19:19 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
ziv-2014 Barlone, Это про декларацию fastcall - у emba и ms они разные. Тут же декларация cdecl - должно работать в первоначальном варианте. Код: pascal 1. 2.
Надо смотреть, что передается в transactionId и как он принимается библиотекой? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2021, 22:14 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
В первую очередь спасибо всем откликнувшимся. Barlone - отдельное спасибо за первую же мысль, оказавшуюся верной. Итак, основная суть проблемы в том, что граждане (не будем показывать пальцами), которые кодят только в Delphi годами (а некоторые и десятилетиями) но примитивный код, не совсем ясно представляют себе саму суть ответа который был дан. Фразовая конструкция "то результат будет в eax:edx" не дает понимания того, что происходит, куда рушится мир... Поскольку на решение было потрачено было неподобающее число времени, и нигде не попался придурковато внятный ответ напишу его тут. В моем случае действительно не хватало пендаля человека, который пишет на С много и часто, без оглядки на переменные. Идеологически правильная декларация функции все же в моем случае должна была выглядеть следующим образом: Код: pascal 1.
Как верно указал Barlone а потом Dimitry Sibiryakov вопрос в том, что нет понимания того, что происходит. в моем случае (задача функции получить идентификатор, и вернуть его же в поле структуры szTransactionID вызываем процедуру с точкой останова после отработавшей процедуры Код: pascal 1. 2. 3. 4. 5. 6. 7.
имеем результатом значение r = 49066528 (Watch list) Именно в настоящий момент начинается "волшебство" для альтернативноодаренных. 1) открываем обычный виндовс калькулятор, переводим его в режим "программист" и взираем на шестнадцатиричное значение 00000002ECB220. (в разных случаях оно может быть разным, но вспомним, что у меня вторая часто структуры перечисление где успешный код = 0 ... т.е. фактически имеет отображение 0000000 2) открываем окно состояния регистров (да-да, то самое, которое открывается когда кошка пробежала по клавиатуре) View \ Debug window \ Registers и наконец начинаем понимать о чем "говорили старые зайцы" увидев напротив строчки именуемой EAX вышеозначенный текст 2ECB220 а напротив EDX 0000000 3) в моем случае первое поле это адрес строки т.е оное значение ищем в окошке содержимого памяти (поскольку об окне содержимого памяти тоже кто-то может не знать, то его найти можно там же рядышком View \ Debug window \ Memory) 4) Грусть и некоторое недоумение настигают обычно когда долистываешь до нужного адреса... по дампу памяти. тихо и смирно там обитает моя исходная строка '234567'#0 которую теперь нужно просто скопировать в свой блок памяти 5) результатом r shr 32 получаем тот блок данных, который превращается в мое перечисление дальнейшие махинации не являются целью текущего поста, картинки во вложении Еще раз всем спасибо. Тема оказалась познавательна ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 02:53 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
Что-то долго и мутно. Реально возвращается структура, умещающаяся в 8 байт в eax:edx, как и сказано на стековерфлоу. Один в один, указатель в младшем и енум в старшем регистрах. Не совсем понятно в чем проблема была ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 03:46 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
white_nigger, все верно, все так и есть... проблема в том, чтобы увязать рухнувшее мировоззрение о том, что: 1) заявленная структура - CTMBeginTransactionResult не заполнится сама 2) структура как результат присвоения впрямую по полям не вычитывается 3) оба регистра можно рассматривать как что-то другое путем манипуляции с другим типом Этот нетиповой для учебника по Delphi комплект допущений слишком примитивен, чтобы зная этот момент, понять чего спрашивают.. Да, я видел этот ответ не один раз пока искал ответ, натыкался на несколько умных статей.. Но регистры процессора и пол-переменной это нештано. Сложилась мозаика - когда сложилась. Последний пост описание - в первую очередь был для тех, кто тоже смотрит на мир через веру в добро, а натыкается на вселенскую несправедливость. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 09:05 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
Borland/Emba идут своим путем, в итоге код получается не совместимым. Поэтому я никогда не передаю в результате функции структуру или вещественные числа. Всегда делаю var параметром. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 09:53 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
maremora, вот прямо по тем двум ссылкам, что тебе кидали явно написано как и что возвращается и как можно и нужно писать, что бы сработало: Си: 'In common x86 calling conventions, objects that fit in two registers are returned in RDX:RAX' Delphi: 'Int64 is returned in EDX:EAX.' авторФразовая конструкция "то результат будет в eax:edx" не дает понимания того, что происходитФразовая конструкция + ссылки описывает и дает ответ на вопрос абсолютно точно и полностью, прямо как в анекдоте про воздушный шар :) Зачем и о чем весь остальной пафос не понятно. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 10:26 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
ziv-2014, где ты конкретно тут видишь свой 'свой путь' - не понятно. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 10:27 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
maremora Идеологически правильная декларация функции все же в моем случае должна была выглядеть следующим образом: Код: pascal 1.
Во-первых, UInt64 более корректно, а во-вторых, это только для х32 ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 10:39 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
white_nigger Что-то долго и мутно. Реально возвращается структура, умещающаяся в 8 байт в eax:edx, как и сказано на стековерфлоу. Один в один, указатель в младшем и енум в старшем регистрах. Не совсем понятно в чем проблема была ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 11:23 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
makhaon, Результаты по некоторым типам в stdcall и cdecl в си и delphi не совпадают. fastcall и register, который по сути тот же fastcall, но со своими особенностями. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 11:26 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
s62 white_nigger Что-то долго и мутно. Реально возвращается структура, умещающаяся в 8 байт в eax:edx, как и сказано на стековерфлоу. Один в один, указатель в младшем и енум в старшем регистрах. Не совсем понятно в чем проблема была Проблема, как я понимаю, в том, что если объявить в Delphi функцию с тем же возвращаемым результатом, как в исходной фунции Си, то в этом возвращаемом результате будет совсем не то, что нужно. Т.е. в Delphi, для 32-битной программы, нужно сделать вот такой хак, как сделал ТС: результат объявить как Int64, а потом, уже после вызова внешней функции, это преобразовать в запись CTMBeginTransactionResult. Именно. Несуразность выливается в то, что вместо прямого импорта функции и далее работы с полями record как это впрямую выглядит, нужно делать дополнительную неявную обвязку, которая будет мониторить "особенности реализации". Это в некоторой мере нелояльно к сотрудникам поддержки. Прочие моменты можно обсуждать и далее. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 12:49 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
Fr0sT-Brutal, Да это так, но разработчики оборудования и не предоставляют и не собираются поставлять библиотек другой битности. По поводу UInt64 замечание корректное, спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 13:00 |
|
Получить структуру из С-шной DLL
|
|||
---|---|---|---|
#18+
maremoraПо поводу UInt64 замечание корректное Вообще-то это без разницы, сдвиги в дельфи не расширяют знак. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2021, 13:23 |
|
|
start [/forum/topic.php?fid=58&fpage=15&tid=2037156]: |
0ms |
get settings: |
8ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
66ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
62ms |
get tp. blocked users: |
2ms |
others: | 250ms |
total: | 424ms |
0 / 0 |