Форум — Ответы ( К темам )
? | 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с) |