Форум: "Потрепаться";
Текущий архив: 2003.07.10;
Скачать: [xml.tar.bz2];
ВнизСтандартный способ передачи параметров в Dll Найти похожие ветки
← →
Andrey (2003-06-18 16:31) [0]Собственно все бы хорошо, но!!! Надо по ссылке передавать, чтоб Dll-ка могла менять значения этих параметров. А возвращаемые значения естественно могут быть больше чем передаваемые.
Короче так. Есть у меня 5 переменных PChar в проэкте, нужно эти переменные передать в библиотеку. Она (библиотека) чего-то с ними делает, в результате после завершения работы библитеки в этих 5 переменных должны быть новые значения.
Вся работа с Dll-кой должна ограничится:
1. загрузил Dll
2. получил адрес проседуры в Dll
3. вызвал процедуру из Dll
4. по завершении работы процедуры выгрузил Dll
Вся проблемма в том что при передаче в Dll PChar-ов я в Dll немогу менять размер выделеный под них.
Глобальные переменные в Dll и borlndmm.dll не предлогать. Все больше склоняюсь к тому, что прийдется делать через GlobalLock...
После столь сумбурного описания задачи, наконец попробую сформулировать вопрос.
Как передать в Dll вкачестве параметра при вызове процедуры указатель на строку, и получить указатель на другую строку, большего размера, при этом не используя ни глобальные переменные в Dll, ни GlobalLock, ни borlndmm.dll?
← →
N169 (2003-06-18 16:35) [1]Передавать адрес некой переменной, гарантированно существующей в то время, как работает ф-я из dll, а в неё заносить адрес динамически выделенной строки.
Память выделять в контексте процесса ф-ей HeapAlloc(), как рекомендует MSDN.
Все дела!
← →
panov (2003-06-18 16:36) [2]Написать свой менеджер памяти, как в BorlndMM.dll
Не мучайся. Намного проще использовать ShareMem.pas
BorlndMM.dll занимает всего 25к.
Причина, по которой не хочешь пользоваться этим, несколько непонятна.
Если все же тебе надо испльзовать строки, то используй PChar, а под результат перед передачей параметра в функцию из DLL выделяй максимальный размер памяти, который может понадобиться функции.
← →
han_malign (2003-06-18 16:44) [3]function fff(const aData; var aSize: DWORD): DWORD;external "myDll";
..........
var sz: DWORD;
..........
sz:=0;
res:=fff(nil^,sz);
if(res=ERROR_MORE_DATA)then begin
GetMem(p,sz);
fff(p^,sz);
....................
FreeMem(p);
end;
З.Ы. Уж не знаю насколько это нормально(я уже привык), но это стандартный подход WinApi.
← →
Andrey (2003-06-18 16:59) [4]>panov
Причина состоит в том что я этим самым BorlndMM никогда не пользовался, а сейчас начинается новый немаленький проэкт и просто страшно использовать непроверенные технологии...
>под результат ... выделяй максимальный размер памяти
Чесно гооря ниэстетично :) Хотя конечно такой вариант имеет право на существование.
>han_malign
Хм... Неуверен, что это хороший стиль (хотя и видел такое в help-ах)... К тому же свсем необязательно, что функция ссамого начала знает сколько под результат нужно места... Например функция которая показывает модальное окно в которое пользователь вводит текст врядли может предугадать сколько пользователь введет символов.
>N169
>HeapAlloc()
Я уже говорил: "Все больше склоняюсь к тому, что прийдется делать через GlobalLock..."
← →
Игорь Шевченко (2003-06-18 17:23) [5]Andrey © (18.06.03 16:59)
> Причина состоит в том что я этим самым BorlndMM никогда
> не пользовался, а сейчас начинается новый немаленький проэкт
> и просто страшно использовать непроверенные технологии...
Вот что странно - Delphi ты использовать не боишься, а borlndmm.dll для тебя непроверенный. Пользователи Borland"а во всем мире его уже много раз проверили, и ничего, довольны.
← →
Andrey (2003-06-18 17:38) [6]>Игорь Шевченко
А я очень долго после Clipper-а и Delphi неверил :)
Вот тут по поисковикам полазил с запросами типа "ошибка при использовании BorlndMM"... немного флуда, а поделу почти ничего, значит можно использовать :) Хотя конечно осторожно... чтоб в любой момент при критическом сбое можно было любой модуль в проэкт намертво (через uses) вкомпилировать :)
← →
nikkie (2003-06-18 17:45) [7]>>N169
>>HeapAlloc()
>Я уже говорил: "Все больше склоняюсь к тому, что прийдется делать через GlobalLock..."
ты наверное GlobalLock не использовал никогда. имхо, HeapAlloc/HeapRealloc - самое красивое решение. другое имхо - при использовании borlndmm использовать эту dll из других языков проблематично будет.
← →
Andrey (2003-06-20 13:14) [8]>nikkie
Ну незнаю незнаю... Вопервых технология HeapAlloc/HeapRealloc выглядит для меня еще более темным лесом чем borlndmm (я API почти не использую, только через VCL стараюсь работать), вовторых пока не планируется подключать модули на других языках, а в третих... ну ненашел я красивого решения как передать в процедуру 4 строки и получить на их место 4 новых строки и все это с помощью HeapAlloc/HeapRealloc
Конкретная задача:
Есть функция в DLL
Connect: function(Database: TIBDatabase;
UserName, UserPs, DBServer, DBPath: string): integer; stdcall;
Если через borlndmm то ничего менять ненадо, можно прямо так и вызывать
Result:=Connect(DM.Db, UserName, UserPs, DBServer, DBPath);
А вот если через HeapAlloc/HeapRealloc то нужно писать нечто типа:
var lUserName, lUserPs, lDBServer, lDBPath: Pointer;
begin
...
lUserName:=HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, Length(UserName));
/* и так для каждой переменной */
Result:=Connect(DM.Db, lUserName, lUserPs, lDBServer, lDBPath);
UserName:=PChar(lUserName);
HeapFree(GetProcessHeap, 0, lUserName);
/* и так для каждой переменной */
Конечно последний блок (UserName:=PChar(lUserName); HeapFree(...)) можно вынести в отдельную процедуру... Но мое IMHO, все это крайне не эстетично :)
Может я пропустил какой-то более простой вариант? Поправте меня пожалуста.
P.S. Глобальные переменные (UserName...) нехочется изначально через HeapAlloc инициализировать, потму что работа с ними сильно усложнится.
Вместо
UserName:=EUserName.Text;
писать
UserName:=HeapReAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, UserName, Length(EUserName.Text)+1);
UserName:=EUserName.Text;
← →
Andrey (2003-06-20 13:20) [9]В догонку...
Наверно Игорю Шевченко. А как borlndmm с Runtime packages работает? В смысле поддерживает ли он их? Или может он только их и поддерживает?
← →
DiamondShark (2003-06-20 13:31) [10]
> А как borlndmm с Runtime packages работает? В смысле поддерживает
> ли он их? Или может он только их и поддерживает?
А с ними он вообще не нужен.
Кстати, если проект задумывается целиком на Дельфи, почему бы не использовать пакеты?
Заморачиваться с ДЛЛ имеет смысл только в случае использования нескольких средств разработки
← →
nikkie (2003-06-20 13:58) [11]>Но мое IMHO, все это крайне не эстетично :)
А по-моему - нормально. Только надо еще из стринга в аллокированную память строку копировать и передавать указатели на PChar, а не сами PChar. Если тебе удобнее использовать string, то пишешь один раз и навсегда юнит с функциями-обертышами.
Кстати, у тебя dll собирается username и т.п. менять? Там что, формочки содержатся? Тогда разумно и о пакетах подумать. А если параметр не меняется, то и HeapAlloc не нужен - просто PChar(UserName) передаешь.
А с GlobalLock получится только больше кода.
GlobalAlloc
GlobalLock
CopyMemory
GlobalUnlock
вызов функции(HGLOBAL)
GlobalLock
s := ...
GlobalUnlock
GlobalFree
← →
Andrey (2003-06-20 14:41) [12]>DiamondShark
>если проект задумывается целиком на Дельфи, почему бы не использовать пакеты?
:) хоть проэкт и задумывается на Delphi, но совсем отгораживатся от других языков тоже нехочется... Типа: "Конечно наш комплекс сможет использовать библиотеку написаную на любом языке, но максимальной эффективности можно дудет добится только с библиотекой написаной на Delphi" а не "К сожалению ваш комплекс несможет работать совместно с нашим через Dll" вот нечто подобное :) Хотя можно возразить, что для связи существует COM и т.д. но это уже не из той оперы.
А про пакеты всетаки надо подумать... И про связь с другими комплексами через COM тоже надо подумать :)... И еще про столько мелочей надо подумать, что жалко свою голову становится :) А SQL-скрипт для формирования базы уже почти готов, и пора клиентов писать... ух блин!!!
Так, что-то я отвлекся.
>nikkie
>Только надо еще...
:) С технологией HeapAlloc/HeapRealloc дела никогда не имел, код не компилировал, Help почитал и на глазок набросал, естественно ошибки. Но проблемма не в этом, а в том, что прийдется под каждую глобальную переменную заводить локальный PChar, и сначала их всех инициировать, а потом назад в глобальные переменные значения возвращать.
>Кстати, у тебя dll собирается username и т.п. менять? Там что, формочки содержатся?
Угу, собирается менять. Угу, формочки содержатся. Вообще библиотека называется Login, а интерфейсная функция Connect. Далее из параметров функции смысл ясен :)
Про пакеты... Наверно Dll и само приложение будем собирать со включенным Runtime packages (это решит проблемму с глобальными переменными Application, Screen...), но Dll всетаки останутся Dll-ками.
Все мечусь между HeapAlloc/HeapRealloc и borlndmm...
← →
nikkie (2003-06-20 16:00) [13]выбирай COM. серьезно.
← →
DiamondShark (2003-06-20 16:10) [14]
> Andrey © (20.06.03 14:41)
Не пойму я никак... Зачем себе жизнь усложнять-то? Модульность в рамках проекта -- это одно, интерфейс со сторонними производителями -- это совершенно другое.
Чего бы для подзадач совершенно разного тиа не взять наиболее адекватные средства?
Нет... не понимаю...
← →
Soft (2003-06-20 17:55) [15]Мой совет... Пиши на Java, все проблемы сами собой отпадут.
← →
Andrey (2003-06-20 21:22) [16]>Soft
Ага, пока я на нем что-нибудь напишу и заказчики тоже отпадут :)
>DiamondShark
Ну не поймешь и ненадо. Если опыта в проэктировании средних (в смысле, не больших не малых, а именно средних) систем у меня нет, естественно я буду валить все в кучу. А опыт я приобрести могу только на практике. Естественно хочется написать что-нибудь более-менее универсальное, что потом ради предоставления интерфейса другим программам непришлось пол-проэкта перелопатить.
>Игорь Шевченко © (18.06.03 17:23)
Дополнение. Я больше не его (borlndmm) ошибок боюсь, а своих. Вдруг чего-то по глупости, незнанию сделаю. У меня работает, а у заказчиков нет.
>nikkie
COM это конечно хорошо... IMHO это из пушки по комарам.
Мне всего то хотелось узнать, какие методы передачи параметров существуют, какие лучше и почему...
Ладно, все, вопрос закрыт. Внутри комплекса использую borlndmm. Для комуникации с другими пиложениями по возможности буду использовать HeapAlloc/HeapRealloc. В крайнем случае COM.
Всем спасибо, камера стоп.
← →
y-soft (2003-06-21 11:37) [17]Всем спасибо, камера стоп
А не рановато ли?:)
Существует еще один вариант решения задачи (довольно широко, кстати, применяется в WinAPI...), который не требует перераспределения памяти в Dll, а следовательно - и применения внешних менеджеров памяти:
Из Dll функция экспортируется примерно так:
function MyFunction(const Buffer; var BufferSize : DWORD) : BOOL;
В параметреBuffer
передается указатель на буфер для записи результата;
В параметрBufferSize
вызывающая программа записывает фактический размер буфера. Dll помещает сюда же фактический размер.
В случае, если размер буфера недостаточен (или возникли еще какие-то ошибки), функция устанавливает код ошибки с помощьюSetLastError
и возвращаетFalse
...
В случае неудачи по причине недостаточного размера буфера вызывающая программа выделяет под буфер необходимый размер памяти и повторно вызывает функцию...
← →
Anatoly Podgoretsky (2003-06-21 11:49) [18]Да это весьма распространенный в WinApi метода. Буфер+Размер+КодОшибки
← →
Andrey (2003-06-23 10:33) [19]>y-soft & Anatoly Podgoretsky
Вообще-то подобный метод уже предлогали panov (18.06.03 16:36) и han_malign (18.06.03 16:44) в разных вариациях...
И я уже ответил на эти предложения Andrey (18.06.03 16:59) :)
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2003.07.10;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.011 c