|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Pascal exe и С++ dll |
|
Pascal exe и С++ dll
|
Пользователь Сообщения: 59 |
Прошу помочь знающих людей, бо сам уже оскомиму набил-таки...
Значит имеется программа написанная на Delphi 7. В ней вызывается dll, следующим образом: -------------------------------------------------- var PlugExec:function(I,R,S,B:pointer;ISize,RSize,SSize,BSize:integer):boolean; IntMas:array[0..72] of ^integer; RealMas:array[0..4] of ^real; StrMas:array[0..29] of ^shortstring; BoolMas:array[0..4] of ^boolean; begin @PlugExec:=nil; NewHandle:=LoadLibrary('C++Plugin.dll')); if NewHandle <> 0 then begin @PlugExec:=GetProcAddress(NewHandle,'PluginExec'); PlugExec(@IntMas,@RealMas,@StrMas,@BoolMas,length(IntMas),length(RealMas),length(StrMas),length(Bool Mas)); end; FreeLibrary(NewHandle); -------------------------------------------------- Теперь код С++ dll-ки (.NET): -------------------------------------------------- extern "C" bool PASCAL EXPORT PluginExec(void *I, void *R, void *S, void *B, int ISize, int RSize, int SSize, int BSize){ int *IntMas; IntMas=new int[ISize]; IntMas=dynamic_cast<int 32*>(I); if (IntMas[5]==4) ... return true; } -------------------------------------------------- В результате выскакивает следуюзая ошибка в строке с dynamic_cast: error C2059: syntax error : 'constant' 1. В чем проблема? Объявить const void *I - та же проблема. 2. Если из Delphi в ISize сидит к примеру 40, то в С++ я виду 1200000 или что-то в этом роде. 3. Адрес ячейки памяти I указывает на 0х000005 чего-то так, то есть область ОС. Указатели без типа несовместимы? Заранее благодарен, за любую предоставленную информацию. |
|
------- Отправлено: 20:59, 05-09-2006 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Server
Можно почитать документацию по dynamic_cast и понять, что а) он здесь не нужен б) синтаксис неправильный. Здесь хватит static_cast'а. Примерно так: IntMas = static_cast<int*>(i). Более того, поскольку фактически void* от int* ничем не отличается, а манглинг имён всё равно не применяется, то можно параметр I сразу сделать типа int*. То что i=(void*)5 навевает на мысль, что конвенции вызова не совпадают и параметры лежат в обратном порядке (т.к. должно быть BSize=5). Что-то мне подсказывает, что PlugExec стоит объявить вот так: Либо убрать PASCAL из объявления функции в сишной реализации. |
------- Отправлено: 22:54, 05-09-2006 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Пользователь Сообщения: 59
|
Профиль | Сайт | Отправить PM | Цитировать ivank
Почему именно static надо применять? Массив я же создаю динамически. Со static dll скомпилена. Массив динамически создается, но поскольку ISize равняется 1000000 и I указывает на системную область памяти - получаем Access Violation. Экстрадиция Pascal из объявления функции - как мертвому припарки. Изменить exe код не представляется возможным. Там нет stdcall. |
------- Отправлено: 23:07, 05-09-2006 | #3 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Server
Курите документацию. Как вы выделяете память не влияет на то, какой *_cast применять. Это зависит сугубо от типов, которые подвергаются преобразованию. Для преобразования void* в int* достаточно static_cast. dynamic_cast нужен при преобразованиях от указателя на предок класса к указателю на наследника. Цитата:
Почему нельзя менять exe? Оптимально изменить именно его, чтобы использовалась конвенция stdcall, потому что про неё все (delphi и VC) всё прекрасно знают, так как она используется при вызове winapi. Это де-факто стандарт. Те, кто не используют эту конвенцию для вызова "инородных" функций - сами себе злобные буратины. Я немножко погуглил и выяснил, что дельфи по умолчанию использует register конвенцию. То есть распихивает первые 3 параметры в регистры (eax, ecx, edx), остальные параметры кладутся на стек согласно паскалевской конвенции. Насколько мне известно VS ничего подобного не знает. Поэтому, если exe менять нельзя для использования более адекватной конвенции, следует написать заглушку, которая будет принимать параметры согласно дельфёвым соглашениям (register), а вызывать функцию согласно согласно соглашениям, которые понимает VS (__cdecl, __stdcall, __pascal, или __fastcall). Если есть желание вставить такую заглушку непосредственно в dll, то придётся писать её на ассемблере. Я, чтобы не мучиться, создал бы dll-заглушку на дельфи. В которой была бы одна функция PlugExec, которая принимает параметры в дельфёвой конвенции register, а вызывает сишный плагин уже с помощью stdcall. Соответственно в сишном плагине заменил бы соглашение для функции PlugExec с PASCAL на __stdcall. upd Повторюсь, резюмируя всё выше сказанное. Либо используйте в exe и dll одно соглашение о вызовах, которое понимае и VS и delphi. К ним относятся: pascal/__pascal, cdecl/__cdecl, stdcall/__stdcall. Перед слышем дано название соглашеия в дельфе, после - в VS. Либо (если exe менять нельзя) пишите заглушку, которая будет принимать парметры в дельфёвом соглашении register, а выдавать их в соглашении, понятном VS (сейчас у вас, судя по коду, сишная функция использует паскалевское соглашение). Подробнее про различные соглашения о вызовах можно почитать в интернете. Погуглив на тему "delphi calling conventions". |
|
------- Отправлено: 00:54, 06-09-2006 | #4 |
Пользователь Сообщения: 59
|
Профиль | Сайт | Отправить PM | Цитировать ivank
Спасибо, разобрался. Действительно нужно вызывать через соглашение stdcall. Получилось получить доступ ко всем параметрам главной программы, однако возник вопрос. В программе на Delphi (этой же) используется тип shortstring. А какой для него аналог использовать в С++? char* не получается. |
|
------- Отправлено: 00:33, 07-09-2006 | #5 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать http://www.google.ru/search?hl=ru&q=...+shortstring+c
Первый байт - длина строки, начиная со второго - сама строка. Без завершающего нуля. |
------- Отправлено: 13:22, 07-09-2006 | #6 |
Старый параноик Сообщения: 2423
|
Профиль | Отправить PM | Цитировать Для продвинутого курения :]
Относительно DLL хорошая статья: http://www.progz.ru/articles.php?issue=9 |
Отправлено: 11:48, 25-09-2006 | #7 |
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Разное - Всё о TURBO PASCAL (обсуждение, помощь в написание программ, ошибки, Pascal ABC) | Loading | Программирование и базы данных | 41 | 20-05-2015 15:28 | |
Разное - Использование команд из user.exe(dll) | n9271217 | Microsoft Windows 2000/XP | 0 | 13-01-2009 14:58 | |
Разделение функций winlogon.exe и msgina.dll | Котяра | Хочу все знать | 2 | 18-07-2008 17:14 | |
Не опознается hal.dll,ntoskrnl.exe,KDCOM.DLL | Igor_strelka | Microsoft Windows 2000/XP | 3 | 12-01-2007 23:23 | |
Написание упаковщика exe, dll на c++ Builder | DIMAIN | Программирование и базы данных | 4 | 30-04-2005 23:44 |
|