Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

не могу правильно указать тип переменных для функций из одной DLL [D6, Win2k]


AlexVit ©   (2002-10-31 08:21:00) 

Я всех привествую!
Беда у меня такая: есть DLL-ка (arGCCsender.dll), написанная на С партнерами фирмы. Они оставили исходники. Вот текст заголовочного файла arGCCsender.h с функциями, которые меня интересуют:
#ifndef arGCCsender_H_INCL
#define arGCCsender_H_INCL
//-----------------------------------------------------------------------------
// Connect/reconnect to machine
extern "C" int argccsender_connect(const char *ip, int port);
// Disconnect
extern "C" int argccsender_disconnect(void);
// Send message to machine
extern "C" int argccsender_send(const char *type, const void *msg, int msglen);
//-----------------------------------------------------------------------------
#endif

я прописываю функции этой DLL в своей программке так:
function argccsender_connect(ip: PChar; port: Integer): integer; external "arGCCsender.dll";
function argccsender_disconnect: integer; external "arGCCsender.dll";
function argccsender_send(ttype: PChar; msg: PChar; msglen: Integer): integer; external "arGCCsender.dll";

А использую так:
...
Edit1.Text := IntToStr(argccsender_connect(PChar("127.0.0.1"), 9017));
...
Edit2.Text := IntToStr(argccsender_send(PChar("TEX"), PChar("123"), 3));
...
Edit3.Text := IntToStr(argccsender_disconnect)
Собственно, проблема вот в чем:
эти функции должны возвращать 0, если они отработали без ошибок. Однако, функции argccsender_connect и argccsender_send возвращают 3, т.е. возникает какая-то ошибка. Функция argccsender_disconnect возвращает 0, т.е. все ОК (и не удивительно, ведь она не имеет входных параметров!).
Подозреваю, что не правильно описал типы параметров, используемых теми двумя функциями. Правда, извращался и так и сяк, но ничего не добился. Вообщем, помогите, будьте добрыми, люди: что я делаю не правильно?

С уважением, AlexVit


Digitman   (2002-10-31 16:58:00) [1]


> AlexVit



> Как говорится, век живи - век учись.


Чем мы тут, собссно, и занимаемся все).. я тоже учусь, в дан.случае - на твоем опыте)


AlexVit   (2002-10-31 16:47:00) [2]

Мужуки, спасибо всем большое, особенно Digitman!
Помогло cdecl. Все заработало. Как говорится, век живи - век учись.
Всем счастливо!!!


Digitman   (2002-10-31 11:40:00) [3]

>Alex4444444444

Далеко не всегда. Это - в зависимости от разработчика и версии компилятора.
В стародавние времена (например, в Quick C) директива extern "C" , кажется, и формировала код в соответствии с соглашениями, ныне "обзываемыми" cdecl. На тот момент устойчивого соглашения, именуемого сейчас как stdcall, как помнится, не фигурировало.
Так что самый надежный (даже в наст.время) способ при таких сомнениях (за неимением инф-ции о версии компилирующей среды ) - трассировка хотя бы одного из экспортируемых вызовов


Alex4444444444   (2002-10-31 11:04:00) [4]

Pohozhe, extern "C" zadaet ih kak cdecl...


Lord Warlock   (2002-10-31 09:48:00) [5]

2 Юрий Зотов © (31.10.02 09:22)
2 Внук © (31.10.02 09:32)

Посмотрел у себя на подобное, Ваша правда.

ЗЫ 2 Внук ©и нечего ржать :)


Digitman   (2002-10-31 09:47:00) [6]

Выдержка из хэлпа :

The cdecl convention is useful when you call functions from DLLs written in C or C++, while stdcall and safecall are used for Windows API calls

Хотя это и не 100%-гарантирует правильность сопряжения, все же думаю, что здесь нужен cdecl.

stdcall требует балансировку стека в теле вызываемой п/п, равно как и по-умолчанию в паскалевских п/п. Здесь же "тройка" осталась в стеке, ибо п/п скорее всего предполагает, что инструкция балансировки стека последует сразу за инструкцией вызова (т.е. в соответствии с cdecl-соглашениями), иначе - каким образом "тройка" могла пересечься с результатом ?

Впрочем выяснить это при желании можно элементарно, оттрассировав код вызова и тела п/п

И вот что мы там увидим :

В stdcall это будет выглядеть след.образом


push ..
push ..
...
push ...
call XXXX


где в теле XXXX возврат осущ-ся по RET N

В cdecl же это выглядит несколько иначе :


push ..
push ..
...
push ...
call XXXX
add esp, ...


где в теле XXXX возврат осущ-ся по RET



Внук   (2002-10-31 09:32:00) [7]

>>Lord Warlock © (31.10.02 09:27)
Поскольку DLL предназначены для использования из программ, написанных на разных языках, и, в общем случае, заранее невозможно узнать, на чем писалась та или иная DLL, то грамотнее было бы применять в них соглашение stdcall, см. Юрий Зотов © (31.10.02 09:22)
То есть, все зависит от дальновидности авторов DLL :))


Lord Warlock   (2002-10-31 09:27:00) [8]

На паскале и С в экспортируемых функциях разный порядок параметров. Для устранения данной проблемы см
Digitman © (31.10.02 08:44)


Юрий Зотов   (2002-10-31 09:22:00) [9]

cdecl или stdcall?
Все же это DLL, там скорее stdcall использовано.


Digitman   (2002-10-31 08:44:00) [10]

function argccsender_connect(ip: PChar; port: Integer): integer; cdecl; external "arGCCsender.dll";

function argccsender_disconnect: integer; cdecl; external "arGCCsender.dll";

function argccsender_send(ttype: PChar; msg: PChar; msglen: Integer): integer; cdecl; external "arGCCsender.dll";


Наверх

Титульная страница Поиск, карта сайта Написать письмо