|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Значение из dll до конца работы функции
Столкнулся сегодня с такой проблемой: в библиотеке у меня определена функция, тип результата которой - array of string. Динамические массива - штука не страшная, и в ходе выполнения функции задать размер массива - естественно, не проблема.
Проблема кроется в следующем: при определении функции в самой программе, используется тот же тип (array of string). И, естественно, я не смогу получить данные из библиотеки до тех пор, пока не укажу размер массива. Собственно, сам вопрос: как мне узнать размер динамического массива, создаваемого в dll, до того, как его значения будут переданы в основную программу? Вот код, используемый в библиотеке (в AdoQuery у меня стоит оператор SELECT) Код:
type TNHArray = array of string; function notesload(uid: integer): TNHArray; var i: integer; begin with datamodule5.adoquery1 do begin sql[1]:='nheader'; sql[3]:=inttostr(uid); active; setlength(result, recordcount); for i:=0 to recordcount do begin result[i]:=fields[i].asstring; end; end; end; З. З. Ы. Возможно, есть более изящное решение задачи, но я его не вижу... Если поможете найти его вместо решения возникшей проблемы, тоже буду очень благодарен |
#2
|
|||
|
|||
Решение - передача в упакованном виде в PChar.
|
#3
|
|||
|
|||
Спасибо большое за совет.
Увы, я перерыл всю собственную литературу, долго искал информацию в интернете, но в результате остался с кучей почти никак не связанных обрывков информации. Что значит "упакованный" PChar? И как его упаковать? Насколько я понимаю, ответив на предыдущие 2 вопроса, я получу ответ на вопрос "Как в одну строку поместить где-то с 15 строковых переменных"? Извиняюсь за назойливость, но тяга к знаниям одолевает Диплом уже есть, а я все никак не успокоюсь |
#4
|
|||
|
|||
0. пишем в dll функцию, которая освобождает блок памяти указанного размера.
1. Анализируем массив (список) строк. Нам надо получить суммарный размер строк + 1 символ для каждой строки + еще 1 символ. 2. Выделяем кусок памяти в PChar размером из п.1. 3. Зануляем его. 4. начинаем запихивать в него наши строки (КОПИРОВАНИЕМ!!!). В конце каждой строки стоит #0, и в конце всего блока памяти стоит еще один #0 (т.е. в самом конце будет #0#0). 5. возвращаем через var параметры указатель на сам блок памяти и переменную с его размером. 6. В основной программе разворачиваем это все обратно и вызываем функцию из п.0 для освобождения памяти. Почему так - не спрашивай. Просто запомни, что память должна быть освобождена в том модуле (dll, exe), где она выделена. Если очень интересно, то читай об управлении памятью. Но проще просто запомнить вышесказанное правило. А вообще, подключи модуль ShareMem (и в exe и в dll) и передавай сразу строки. Только тогда не на Дельфе не получится ничего написать в такую систему. |
#5
|
|||
|
|||
Спасибо большое за развернутый ответ
А можно еще подробней по некоторым пунктам? :-[ 1. Что значит "Занулить память"? 2. Что значит "запихивать копированием"? Оператор присвоения ":=" не пройдет? Как раз задумался о том, что с обычными строками лучше не надо делать: вполне возможно, будет вестись разработкамодулей и на других языках... В общем, как проект раскручу, так и будет) Остальное, вроде бы, понятно, завтра вечерком примусь за реализацию |
#6
|
|||
|
|||
1. FillChar(P,#0);
2. StrCpy() |
#7
|
|||
|
|||
"завтра вечером" немного затянулось. сел только сегодня))
Большое спасибо за помощь! |
#8
|
|||
|
|||
Опять напоролся
Код:
strcopy(PChar1, String1) Incompatible types: 'String' and 'PAnsiChar' Как надо поступить в сложившейся ситуации? UPD: Вы имели ввиду StrCopy (Delphi) или StrCpy (C)? Последний раз редактировалось Эллурн, 16.12.2010 в 02:57. |
#9
|
|||
|
|||
Пример из справки дельфей:
Код:
procedure TForm1.Button1Click(Sender: TObject); var Buffer: PChar; begin GetMem(Buffer,Length(Label1.Caption) + Length(Edit1.Text) + 1); StrCopy(Buffer, PChar(Label1.Caption)); StrCat(Buffer, PChar(Edit1.Text)); Label1.Caption := Buffer; Edit1.Clear; FreeMem(Buffer); end; |
#10
|
|||
|
|||
Спасибо большое! Очень помогли =)
|
#11
|
|||
|
|||
Извиняюсь, что возвращаюсь к этой теме.
Касательно процедуры, освобождающей память, занимаемую указателем из библиотеки: как ее реализовать? Я на радостях написал просто Код:
procedure FreeMyMemory (p: PChar); begin freemem(p); end; Мне показалось, в принципе, это вполне логично: я же передаю в процедуру не саму переменную, а только ее значение, и указывает она уже совсем не на те адреса в памяти. Тем не менее, я не знаю, что делать. |
#12
|
||||
|
||||
Код:
program Project1; {$APPTYPE CONSOLE} var c: PChar; procedure FreeMyMemory(c: PChar); begin FreeMemory(c); end; begin c:=GetMemory(1); c^:='@'; Writeln(c^); FreeMyMemory(c); Readln; end. Пишу программы за еду. __________________ |
#13
|
|||
|
|||
Путем кучи изменений, лог которых не остался в моей памяти, у меня получилось это) И, естественно, благодаря вашему совету
Однако, вот такая теперь ситуация: в основной программе, после того, как я принимаю значение Pchar, происходит следующее: Код:
p:=HeaderLoad(strtoint(uid.caption), len, hcount); //Вызов ф-ции из dll ......... p1:=AllocMem(len); p1:=p; setlength(harray, hcount); i:=0; ii:=0; repeat if p1^<>#1 then begin harray[i]:=harray[i]+p1^; inc(p1); ii:=0; end else begin inc(i); inc(ii); inc(p1); end; until ii=2; Как мне освободить память, выделенную строкой p1:=AllocMem(len);? Другого способа "вытащить" строки из P, кроме как перебором по 1 символу, я не вижу, а если делать так, то указатель P1 указывает уже не на тот адрес, на который указывал при выделении памяти. Соответственно, освободить память не получится. |
#14
|
|||
|
|||
Ура, почти разобрался сам))
Я просто использовал dec(p1) столько же раз, сколько использовал inc(p1). Но вот незадача: теперь вылетает такое сообщение об ошибке: "Access violation at address 004023EA in module 'Project1.exe'. Read of address 078158FC". Подскажите, пожалуйста, чем дело? |
#15
|
|||
|
|||
А что, указатель нельзя скопировать и работать с копией, а орининальное значение не трогать?
|