Форум: "Основная";
Текущий архив: 2002.11.11;
Скачать: [xml.tar.bz2];
Внизне могу правильно указать тип переменных для функций из одной DLL Найти похожие ветки
← →
AlexVit (2002-10-31 08:21) [0]Я всех привествую!
Беда у меня такая: есть 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 08:44) [1]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";
← →
Юрий Зотов (2002-10-31 09:22) [2]cdecl или stdcall?
Все же это DLL, там скорее stdcall использовано.
← →
Lord Warlock (2002-10-31 09:27) [3]На паскале и С в экспортируемых функциях разный порядок параметров. Для устранения данной проблемы см
Digitman © (31.10.02 08:44)
← →
Внук (2002-10-31 09:32) [4]>>Lord Warlock © (31.10.02 09:27)
Поскольку DLL предназначены для использования из программ, написанных на разных языках, и, в общем случае, заранее невозможно узнать, на чем писалась та или иная DLL, то грамотнее было бы применять в них соглашение stdcall, см. Юрий Зотов © (31.10.02 09:22)
То есть, все зависит от дальновидности авторов DLL :))
← →
Digitman (2002-10-31 09:47) [5]Выдержка из хэлпа :
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
← →
Lord Warlock (2002-10-31 09:48) [6]2 Юрий Зотов © (31.10.02 09:22)
2 Внук © (31.10.02 09:32)
Посмотрел у себя на подобное, Ваша правда.
ЗЫ 2 Внук © и нечего ржать :)
← →
Alex4444444444 (2002-10-31 11:04) [7]Pohozhe, extern "C" zadaet ih kak cdecl...
← →
Digitman (2002-10-31 11:40) [8]>Alex4444444444
Далеко не всегда. Это - в зависимости от разработчика и версии компилятора.
В стародавние времена (например, в Quick C) директива extern "C" , кажется, и формировала код в соответствии с соглашениями, ныне "обзываемыми" cdecl. На тот момент устойчивого соглашения, именуемого сейчас как stdcall, как помнится, не фигурировало.
Так что самый надежный (даже в наст.время) способ при таких сомнениях (за неимением инф-ции о версии компилирующей среды ) - трассировка хотя бы одного из экспортируемых вызовов
← →
AlexVit (2002-10-31 16:47) [9]Мужуки, спасибо всем большое, особенно Digitman!
Помогло cdecl. Все заработало. Как говорится, век живи - век учись.
Всем счастливо!!!
← →
Digitman (2002-10-31 16:58) [10]
> AlexVit
> Как говорится, век живи - век учись.
Чем мы тут, собссно, и занимаемся все).. я тоже учусь, в дан.случае - на твоем опыте)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.11.11;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.008 c