Форум — Ответы     (  К темам )
 ?  Fantom: Вызов ф-ии из ДЛЛ-ки, в сигнатуре кот. есть AnsiString (09-04-2003 18:36:23)
Суть вот в чем:
использую чужую ДЛЛ-ку (писаную на Делфи, гружу динамически) в интерфейсе вызова кот. есть переменные типа string(т.е. наши AnsiString), ну я как полагается, для ипользования AnsiString в интерфейсе вызова, добавил в тело проэкта MEMMGR.LIB, но по окончанию выполнения выдается матюк (ексес виолейшн по такому то адресу). Состыковавшись с разработкичом ДЛЛ-ки — путем заглушек выяснили что вываливается по выходу из ф-ии, т.е. на последнем end
Что может быть?
Зараннее благодарен за помощь!
 Георгий (09-04-2003 20:53:56)
это похоже не правильная работа со стеком проверь прототип функции, которую из DLL вызываешь.
 Игорь (10-04-2003 11:44:34)
Подобное у меня было, если в прототипе функция описана как
WINAPI, поставил _EXPFUNC — все стало ОК.
Просто ранее загрузка и экспорт ф-ции были ориентированы под VC++.
Там(в VC++) c WINAPI экспорт работал на ура, а под Билдер при выходе из ф-ции рушился стек. Замена на _EXPFUNC помогла.
 Fantom (10-04-2003 13:05:35)
Да ворде все честно; привожу кусок кода — может кто чего сразу заметит, что не так:

-------------------------------------------------------------------------
Делфёвый интерфейс: FunKeyM = Function(typ,cod:byte;id_from,id_to,pw,path_IN,path_OUT:string;
var mess:string;Handd:HWND=0):TRetCript;stdcall;
-------------------------------------------------------------------------

//У меня соотв. получилось так(все ифы и проверки на исключения выкинуты дабы незагромождать суть):
...
//описалово ф-ии
typedef TRetCript (__stdcall *FunKeyM)(unsigned char, unsigned char, AnsiString, AnsiString, AnsiString, AnsiString, AnsiString,
AnsiString&, HWND = 0);
FunKeyM KeyM;
//-----------------------------------------------------------------

/* в тело проекта добавил: USELIB("memmgr.lib"); */
//Загрузка ДЛЛ-ки...
{
HINSTANCE dllInst;
void *fun;

//Гружу ДЛЛ-ку
dllI = LoadLibrary(dll_name.c_str());

//Получаю указатель на ф-ию
fun = GetProcAddress(dllInst, "KeyM");

//Преобразовываю в нужный мне вид
KeyM = FunKeyM(fun);
}


//Ф-ия обработки
{
...
//Вызываем ф-ию
rez = KeyM(a, t, d, "", "", "", "", m); /*вот тут и лажа, все как я писал в первом сообщении */
...
FreeLibrary(GetModuleHandle(dll_name.c_str()));
}

На мой взгляд все честно! :(

Если кто понял в чем лажа — подскажите плиз!
Зараннее благодарен за помощь!
 Petro (10-04-2003 15:13:34)
Ты уверен, что string в делфи и AnsiString в билдере — одинаковые объектные типы??? Я бы поставил перед вызовом функции asm int 3 и посмотрел, что там происходит.
 Георгий (10-04-2003 18:46:05)
пришли на мыло скомпилированную длл — как я понял ты с асм не дружишь, а я в отладчике погуляю посмотрю в чём дело...
Результат просмотра здесь напишу.
 Георгий (11-04-2003 00:09:54)
аргумент 't' — 1-й (не 0-й) аргумент в стеке у меня по адресу 0x12F350
далее в dll у меня вылет на такой последовательности:
mov eax,[ebp+0x8];//ebp=0x12f348
mov byte ptr [eax+0x8],0;

выводы:
аргумент 't' — 1-й аргумент — используется как адрес какой то структуры и в неё записывается число (в данном случае 0)
НО по прототипу это не адрес структуры, а обычное число (0-255) которое при использовагии в качестве адреса ведёт в чужую область памяти.

общий вывод — что-то с прототипом не то (или с моими руками)

вопросы:
какое выравнивание использовалось при компиляции DLL (data aligment)
и чему было равно Huge strings тогда же?
 Fantom (11-04-2003 11:59:37)
Спасибо Георгий! Идею понял, хотя не в 1-м параметре, а в возвращаемом значении ф-ии(структура) было дело;
уже нашел где подкололся:
при преобразовании Дельфевого string[размер] я не досмотрел и поставил просто Ansistring, а нужно было: SmallString<размер>, так что все зажило, хотя после обработки по выходу из моей ф-ии вылетает ЕксесВиолейшн, но думаю я просто пока не в курсе о каких то спей действиях при работе с этой ДЛЛ (буду долбать разработчика).

P.S. А голочки у него установленны!

Огромное спасибо всем, кто помог!!!
 Alexander (11-04-2003 15:03:02)
Вывод: не используйте паскалевские короткие строки!
Если надо вовне что-то строковое выдавать, используйте блин pchar (0-terminated string). И наконец, в Билдере можно писать паскалевские модули. Напиши на Object Pascal модуль, который с этой DLL общается, проще будет, однако. А функции этого модуля уже вызывать из сишного модуля.
 Fantom (16-04-2003 15:18:41)
Привет коллеги!
Еще пара слов по вышеизложенной теме:
Беды мои прошли токо тогда, когда чувак кот. писал ДЛЛ-ку на Делфи переделал вх.\вых. переменный типа string на PChar.

Так что, мораль такова:
НЕ ИСПОЛЬЗУЙТЕ в описании ДЛЛ-ных ф-ий строковые переменные типа: AnsiString(string), а пользуйте char*(PChar).
 Alexander (16-04-2003 16:28:33)
Кстати, у AnsiString перед данными не только длина строки хранится, а еще и счетчик числа ссылок — оба по 4 байта (всего 8).
Всем рекомендую для глуюокого изучения таких вещей книжку Marco Cantu — Mastering Delphi (в изд. Питер называется "Delphi Для профессионалов"). У чувака еще и сайт где-то есть.
 Георгий (16-04-2003 17:35:22)
Alexander:
счётчик ссылок — это побочный эффект "умных" указателей (книга — С++, Д.Элджер, Питер 2001, 320с)