Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.07.10;
Скачать: CL | DM;

Вниз

Стандартный способ передачи параметров в 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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.017 c
7-31541
anfaenger
2003-04-28 15:09
2003.07.10
Русский шрифт в меню под не русским Windows.


1-31317
Hollander
2003-06-26 21:08
2003.07.10
Из системы открывают файл, как его загрузить в Memo


4-31559
SerVel
2003-05-07 13:51
2003.07.10
CreateFileMapping(....) весь текст


1-31213
softmaster
2003-06-28 19:20
2003.07.10
экранные координаты


7-31526
onezero
2003-04-27 14:21
2003.07.10
Как изменить системное время программно? Помогите!!!