Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Pascal exe и С++ dll

Ответить
Настройки темы
Pascal exe и С++ dll

Пользователь


Сообщения: 59
Благодарности: 0

Профиль | Сайт | Отправить PM | Цитировать


Прошу помочь знающих людей, бо сам уже оскомиму набил-таки...
Значит имеется программа написанная на 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 чего-то так, то есть область ОС. Указатели без типа несовместимы?

Заранее благодарен, за любую предоставленную информацию.

-------
Windows 2000 forever!


Отправлено: 20:59, 05-09-2006

 

редкий гость


Сообщения: 1696
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


Server
Можно почитать документацию по dynamic_cast и понять, что а) он здесь не нужен б) синтаксис неправильный. Здесь хватит static_cast'а. Примерно так: IntMas = static_cast<int*>(i). Более того, поскольку фактически void* от int* ничем не отличается, а манглинг имён всё равно не применяется, то можно параметр I сразу сделать типа int*.

То что i=(void*)5 навевает на мысль, что конвенции вызова не совпадают и параметры лежат в обратном порядке (т.к. должно быть BSize=5). Что-то мне подсказывает, что PlugExec стоит объявить вот так:
Код: Выделить весь код
PlugExec:function(I,R,S,B:pointer;ISize,RSize,SSize,BSize:integer):boolean; stdcall;
Либо убрать PASCAL из объявления функции в сишной реализации.

-------
http://ivank.ru


Отправлено: 22:54, 05-09-2006 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Пользователь


Сообщения: 59
Благодарности: 0

Профиль | Сайт | Отправить PM | Цитировать


ivank
Почему именно static надо применять? Массив я же создаю динамически.
Со static dll скомпилена. Массив динамически создается, но поскольку ISize равняется 1000000 и I указывает на системную область памяти - получаем Access Violation.

Экстрадиция Pascal из объявления функции - как мертвому припарки. Изменить exe код не представляется возможным. Там нет stdcall.

-------
Windows 2000 forever!


Отправлено: 23:07, 05-09-2006 | #3


редкий гость


Сообщения: 1696
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


Server
Курите документацию. Как вы выделяете память не влияет на то, какой *_cast применять. Это зависит сугубо от типов, которые подвергаются преобразованию. Для преобразования void* в int* достаточно static_cast. dynamic_cast нужен при преобразованиях от указателя на предок класса к указателю на наследника.

Цитата:
Экстрадиция Pascal из объявления функции - как мертвому припарки. Изменить exe код не представляется возможным. Там нет stdcall.
Слишком кратко, а поэтому непонятно.

Почему нельзя менять 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".

-------
http://ivank.ru


Отправлено: 00:54, 06-09-2006 | #4


Пользователь


Сообщения: 59
Благодарности: 0

Профиль | Сайт | Отправить PM | Цитировать


ivank
Спасибо, разобрался. Действительно нужно вызывать через соглашение stdcall. Получилось получить доступ ко всем параметрам главной программы, однако возник вопрос.
В программе на Delphi (этой же) используется тип shortstring. А какой для него аналог использовать в С++? char* не получается.

-------
Windows 2000 forever!


Отправлено: 00:33, 07-09-2006 | #5


редкий гость


Сообщения: 1696
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


http://www.google.ru/search?hl=ru&q=...+shortstring+c

Первый байт - длина строки, начиная со второго - сама строка. Без завершающего нуля.

-------
http://ivank.ru


Отправлено: 13:22, 07-09-2006 | #6


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Для продвинутого курения :]
Относительно DLL хорошая статья: http://www.progz.ru/articles.php?issue=9

Отправлено: 11:48, 25-09-2006 | #7



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Pascal exe и С++ dll

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Разное - Всё о 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




 
Переход