Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 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
1-31194
Mishenka
2003-06-28 04:04
2003.07.10
Как в TreeView определить количество узлов верхнего уровня?


1-31184
Lysyj
2003-06-26 08:39
2003.07.10
Общие свойства компонентов


7-31529
GIMLI
2003-04-20 13:53
2003.07.10
имя Материнской платы


4-31581
Top Gun
2003-05-10 14:30
2003.07.10
Как удалить окно в системе ?


11-31168
IZVER
2002-11-01 13:09
2003.07.10
Как сохранить stream в файл?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский