-
Поясните, пожалуйста, как понять следующий отрывок кода: caption:=Trim(TMibIfTable(_p^).table[i].bDescr);
точнее, если есть структура TMibIfTable, то как понять обращение к ней через указатель? Вот код процедуры:
procedure TForm1.Timer1Timer(Sender: TObject);
var
_MibIfTable:PMibIfTable; _P:Pointer;
i:integer;
_buflen:dword;
_error:dword;
begin
listview1.Items.Clear;
_buflen:=sizeof(_MibIfTable^);
New(_MibIfTable);
_P:=_MibIfTable;
_error:=GetIfTable(_MibIfTable, @_buflen, false);
if _error <> NO_ERROR then
begin
ShowMessage('Произошла ошибка!');
Exit;
end;
for i:=0 to TMibIfTable(_P^).dwNumEntries-1 do
with ListView1.Items.Add do
begin
caption:=Trim(TMibIfTable(_p^).table[i].bDescr);
subitems.Add(GetInterfaceType(TMibIfTable(_P^).table[i].dwtype));
subitems.Add(GetStrMac(TMacAddress(TMibIfTable(_p^).Table[i].bPhysAddr),
TMibIfTable(_p^).table[i].dwPhysAddrLen));
subitems.add(SpeedToStr(TMibIfTable(_p^).table[i].dwSpeed));
subitems.Add(Traff(TMibIfTable(_p^).table[i].dwOutOctets));
subitems.Add(Traff(TMibIfTable(_p^).table[i].dwInOctets));
subitems.Add(IntToStr(TMibIfTable(_p^).table[i].dwOutErrors));
subitems.Add(IntToStr(TMibIfTable(_p^).table[i].dwInErrors));
end;
dispose(_MibIfTable);
end;
Собственно интересует только интерпретация этого выражения для понимания "человеческим" языком. Помогите, Мастера!
-
точнее, если есть структура TMibIfTable, то как понять обращение к ней через указатель?
вот так буквально и понять
-
Пожалуйста, без издевательств, поясните, почему обращение происходит именно таким образом?
-
Потому что кто-то не хотел передавать всю струткуру, а только четыре байта указателя на нее
-
потому что автору так захотелось. кстати, автор несколько неумён.
--- All Your Base Are Belong to Us
-
То есть, в общем случае, если существует запись
Type TStruct = record x1: Integer; x2 : string; end;
и объявлено, что PStruct = ^TStruct, то можно использовать
_pstruct: pstruct; p : ponter; ... new(_pstruct); // это обязательно? p = _pstruct; ... и такую конструкцию: TStruct(p^) ? Верно? И еще: что она вернет?
-
new(_pstruct); // это обязательно?
нет. не обязательно. только если нужно.
и такую конструкцию: TStruct(p^) ? Верно? И еще: что она вернет? TStruct и вернет.
-
какая-то жуткая помесь турбопаскаля и делфи
-
Не совсем ясно, как это? То есть она вернет структуру, заполненную данными (ну был вызов GetIfTable), или пустую, с начальными значениями (после инициализации)? То есть таким образом, имея разные указатели и передавая их как TStruct(p1^), TStruct(p2^), мы будем получать различные наполненные (ессно, после вызова функций заполнения или делая это сами, типа TStruct(p2^).x1 L= 5;) структуры? Я верно понял?
2: Кетмар: а в чем сглупил автор?
-
>[7] wl © (2008-07-07 16:41:00) это no-brain порт с C, похоже.
--- All Your Base Are Belong to Us
-
2 wl : простите, я только учусь....
-
>[8] ob_kun (2008-07-07 16:44:00) >а в чем сглупил автор? в том, что вовремя лечебной эвтаназии не выпил. тут весь код -- сплошная бугогашечка, проще сказать, в чём не сглупил: begin и end правильно написал.
--- Understanding is not required. Only obedience.
-
Не совсем ясно, как это?
Да вот так.
-
или пустую, с начальными значениями
Что лежало в p^ на момент приведения к TStruct то и вернет
-
> Да вот так.
Ответьте, пожалуйста, я верно понял про то, что, имея различные указатели, мы можем таким образом обращаться к различным структурам?
2 ketmar: а как бы сделали Вы?
-
> Что лежало в p^ на момент приведения к TStruct то и вернет
p - указатель, по сути, на структуру. А почему нельяз просто написать так: p^.x1, например?
-
Можно. Кто сказал что нельзя?
-
А зачем тогда заключать указатель внутрь такой конструкции?
-
Это чтобы тебе не скучно было
-
Извините, но серьезно можно ответить? Вы намекаете, что будет синтаксическая ошибка при варианте p^.x1 ?
-
не будет никакой ошибки
-
Тебе намекают, что переменная p тут вообще не нужна. Вот этого достаточно с тем же успехом: caption:=Trim(_MibIfTable.table[i].bDescr);
-
>[14] ob_kun (2008-07-07 16:48:00) >а как бы сделали Вы? во-первых, приведение типов лишнее. во-вторых, работа с динамической памятью (если судить по алгоритму) лишняя. в третьих, поскольку это таймер, то не надо каждый раз перезаполнять список, полагаю, достаточно будет проверить на изменения. дальше — смотреть на задачу конуретней.
--- Do what thou wilt shall be the whole of the Law.
-
>[14] ob_kun (2008-07-07 16:48:00)ну и, кстати, код вообще фиготень. глянуть вот сюда: http://msdn.microsoft.com/en-us/library/aa365943(VS.85).aspx и понять, что если ЭТО работает, то оно не виновато, оно нечаянно. --- Understanding is not required. Only obedience.
-
Как я люблю ShowMessage('Произошла ошибка!'); в таймере !!!
-
>[24] int64 (2008-07-07 18:08:00) кстати, да. этот чудесный момент я вообще провтыкал. за это автору отдельный респектище, юзеры будут очень довольны. %-)
--- Understanding is not required. Only obedience.
-
2 Сергей М : то есть автор просто замудрил с записью, и можно писать проще?
Int64, ketmar: как я понял, делаем в этом случае ShowMessage и Timer1.Enabled := False;
:-)
-
2 ketmar: и еще, Вы предлагаете делать, как я понял, изменение трафика (числа ошибок/скорости etc.) для элемента, название которого в списке соотвествует возвращенному функцией, на первый отсчет таймера - просто производить добавление всех элементов, на последующие - только изменять в соответственных строках значения параметров (поскольку маловероятно внезапное подключение сетевой карты ;) ). Верно я понял?
-
>[26] ob_kun (2008-07-08 10:46:00) >делаем в этом случае ShowMessage и Timer1.Enabled := False; или так. (ц) но вообще-то, рисовать диалоговые окна из обработчика таймера — моветон.
>[27] ob_kun (2008-07-08 10:57:00) и это тоже. так эстетичней. плюс — внимательно почитать ссылку на msdn, которую я привёл, потом код из вопроса, и понять, что код неверный. переписать в соответствии с msdn. потом ещё подумать и вообще прекратить выдылеять/освобождать память в обработчике таймера (кроме самого первого раза, когда поле проинициализируется).
хинт: локальную переменную делаем полем формы. поскольку вызов пинается по таймеру — явно не стоит дополнительно память насиловать, ей и так от строк печально.
--- Do what thou wilt shall be the whole of the Law.
-
> ob_kun (08.07.08 10:46) [26]
Это же очевидно)
-
>[29] Сергей М. © (2008-07-08 11:30:00) ага, как штаны получил — загордился, перестал разгромные ответы писать! %-)
--- All Your Base Are Belong to Us
-
> ketmar © (08.07.08 11:35) [30]
Подожди, еще не вечер) Вожжа под хвост - неприятность малопредсказуемая)
-
>[31] Сергей М. © (2008-07-08 11:45:00) >Вожжа под хвост — неприятность малопредсказуемая) я даже боюсь представить, чем ещё штаны оборудованы…
--- All Your Base Are Belong to Us
-
2 ketmar : Извините, не могли бы вы помочь перевести (или хотя бы пояснить смысл) сишной строки pIfTable = (MIB_IFTABLE *) MALLOC(sizeof (MIB_IFTABLE)); Также: как я понимаю, заголовочника для Delphi нет, необходимо экспортировать функцию из динамической библиотеки, а описания структур оставить в программе, которые и были?
-
> pIfTable = (MIB_IFTABLE *) MALLOC(sizeof (MIB_IFTABLE));
New(pIfTable);
-
> Palladin
я и не ожидал, что так коротко) А разве в C++ нет ничего типа New?
-
MALLOC как видишь
-
>[33] ob_kun (2008-07-08 15:29:00) >как я понимаю, заголовочника для Delphi нет не факт. у джедаев этих заголовков…
--- Do what thou wilt shall be the whole of the Law.
-
>[35] ob_kun (2008-07-08 15:36:00) >А разве в C++ нет ничего типа New? есть. так и называется — new. только оно совсем для другого. остальное — GetMem(sizeof(…)).
--- Understanding is not required. Only obedience.
-
ob_kun Дополнение к ketmar Джедаи это delphi-jedi.org
-
>[39] AlexKniga © (2008-07-08 15:52:00) а, ну да. tnx. провтыкал, должен был сам адрес дать. %-)
--- Understanding is not required. Only obedience.
-
> ketmar © (08.07.08 15:47) [38]
а код похоже на чистом С, там вроде не было new
-
Еще один вопрос: насколько я разобрался в коде, там идет показание параметров соединений только один раз. Стоит так и оставить таймер для обновления данных?
-
>[41] wl © (2008-07-08 15:55:00) >а код похоже на чистом С неа. цпп. в чистом C можно void * присваивать любому указателю, а цпп это запрещает. отсюда там приведение типа.
--- Do what thou wilt shall be the whole of the Law.
-
>[42] ob_kun (2008-07-08 15:58:00) а это тебе видней. там же не готовая софтина, там просто пример правильного использования API.
--- All Your Base Are Belong to Us
-
ketmar, а как понять вашу фразу про "локальную переменную"? Все переменные, использующиеся в var внутри Timer1Timer, перенести в private у формы?
-
>[45] ob_kun (2008-07-08 16:34:00) зачем же все? только буфер с результатом.
зыж я тут один, лучше на ты.
--- All Your Base Are Belong to Us
-
>[45] ob_kun (2008-07-08 16:34:00) точнее, буфер и его размер.
--- Understanding is not required. Only obedience.
-
То, что обозначено как pIfTable и dwSize в указанном тобой примере?
-
>[48] ob_kun (2008-07-08 16:57:00)угу. с достаточно большой вероятностью они после первого «устаканивания» размера изменяться не будут, зачем каждый раз создавать и уничтожать буфер? это имеет смысл, если функция вызывается один раз, а если по таймеру — никакого смысла нет. вообще, вызов GetIfTable() вместе с "устаканиванием" есть смысл вытащить в отдельный метод, нечего обработчик захламлять деталями. да и обновление списка тоже. пусть в обработчике останется нечто типа:
GetIfInfo();
UpdateIfList();
и хватит. зыж pdwSize (какой, всё-таки, идиот их научил понимать венгерскую нотацию так…) --- Understanding is not required. Only obedience.
-
Извини, я написал простой код, он чисто показать, как я понял переписывание функции, можешь посмотреть, если сюда напишу?
-
procedure TForm2.tmrTimer(Sender: TObject);
var
dwSize : DWORD;
dwRetVal : DWORD;
i, j : Integer;
pIfTable : PMibIfTable;
pIfRow : PMibIfRow; begin
New(pIfTable);
if pIfTable = Nil then exit;
dwSize := sizeOf(TMibIfTable);
if GetIfTable(pIfTable, @dwSize, False) = ERROR_INSUFFICIENT_BUFFER then
begin
Dispose(pIfTable);
GetMem(pIfTable, dwSize); if pIfTable = Nil then exit;
end;
dwRetVal := GetIfTable(pIfTable, @dwSize, False);
if dwRetVal <> NO_ERROR then exit;
for i := 0 to pIfTable.dwNumEntries-1 do
begin
if not Flag then begin
with lv.Items.Add do
begin
Caption := Trim(IntToStr(pIfTable.Table[i].dwIndex)+' '+pIfTable.Table[i].bDescr);
end;
end;
end;
if not Flag then Flag := True;
end;
-
>[50] ob_kun (2008-07-08 17:08:00) посмотреть могу. и не только я. %-) я тут далеко не самый умный.
--- Do what thou wilt shall be the whole of the Law.
-
Ну вот, собственно, мой убогий сорец ;)
-
>[51] ob_kun (2008-07-08 17:12:00) не совсем так. а точнее, совсем не так. ну, проверки пока опустим, фиг с ними. ты про обновление списка не понял.
смотри, после первого вызова у тебя уже есть заполненый список. при повторном вызове надо (грубо, можно умнее, но это сейчас не важно) пройтись по списку и проверить, нет ли уже такого элемента в списке. почти наверняка он есть — вот тут достаточно обновить элемент, а не создавать новый. в первом варианте список чистился и заново заполнялся каждый раз — вот это лишнее. достаточно проверить, если ли уже в списке такой элемент и обновить только нужные поля. а вот если нет — тогда создать. а если остались элементы, которые на данном шаге не обновлялись — то их выкинуть.
ну, и BeginUpdate()/EndUpdate() нелохо бы, в виде той же косметики.
--- Do what thou wilt shall be the whole of the Law.
-
>[51] ob_kun (2008-07-08 17:12:00)т.е. "в лоб" нечто вроде:
foreach ifItem in pIfTable do
if IsItemInList(ifItem) then ОбновитьЭлементИОтметитьКакОбновлённый();
else ДобавитьЭлементИОтметитьКакОбновлённый();
end;
end;
...
foreach liItem in list do
if НеОтмеченКакОбновлённый(liItem) then УдлалитьИзСписка(liItem); end;
end;
думаю, псевдокод понятен? %-) --- Do what thou wilt shall be the whole of the Law.
-
Да нет, это как раз я понял. Я уже дописал вариант, но он падает, взгляни: (SubItems [3] - это скорость)
procedure TForm2.tmrTimer(Sender: TObject);
var
dwSize : DWORD;
dwRetVal : DWORD;
i, j : Integer;
pIfTable : PMibIfTable;
pIfRow : PMibIfRow; begin
New(pIfTable);
if pIfTable = Nil then exit;
dwSize := sizeOf(TMibIfTable);
if GetIfTable(pIfTable, @dwSize, False) = ERROR_INSUFFICIENT_BUFFER then
begin
Dispose(pIfTable);
GetMem(pIfTable, dwSize); if pIfTable = Nil then exit;
end;
dwRetVal := GetIfTable(pIfTable, @dwSize, False);
if dwRetVal <> NO_ERROR then exit;
for i := 0 to pIfTable.dwNumEntries-1 do
begin
if not Flag then begin
with lv.Items.Add do
begin
Caption := Trim(pIfTable.Table[i].bDescr);
SubItems.Add('');
SubItems.Add('');
SubItems.Add(SpeedToStr(pIfTable.Table[i].dwSpeed));
end;
end
else
begin
for j := 0 to pIfTable.dwNumEntries-1 do
begin
if Trim(pIfTable.Table[j].bDescr)=lv.Items[j].Caption then
begin
lv.Items[j].SubItems[3] := SpeedToStr(pIfTable.Table[i].dwSpeed);
exit;
end;
end;
end;
end;
if not Flag then Flag := True;
end;
-
Подправил ошибки, но все равно бага.... правлю...
-
>[56] ob_kun (2008-07-08 17:23:00) зачем тебе Flag? процесс заполнения/изменения списка абсолютно не зависит от того, вызвали ли его в первый раз или в сотый. в первый раз ветка «если ли уже всписке» просто всегда будет возвращать false — и что? пусть себе. алгоритм не меняется.
алсо, с чего ты решил, что pIfTable.dwNumEntries и lv.Items.Count равны? это никак не гарантируется, нет такого обещания.
почитай мой псевдокод внимательней, он совсем не то, что ты написал.
--- All Your Base Are Belong to Us
-
>[57] ob_kun (2008-07-08 17:30:00) бага для начала в логике.
--- Understanding is not required. Only obedience.
-
Так и есть, убедился эмпирически сейчас ;)
> ОбновитьЭлементИОтметитьКакОбновлённый();
как понять - отметить как обновленный?
-
foreach ifItem in pIfTable do
и откуда взялось ifItem?
-
Кроме того, не совсем ясна твоя логика: смотри, вот у нас список 1 5 2 300 3 44
и если 1 есть, то обновим его и пометим как обновленный, если, скажем, 4 нету, то добавим и пометим как обновленный. А откуда ж тогда возьмутся необновленные?
-
>[60] ob_kun (2008-07-08 17:35:00) >как понять — отметить как обновленный?у каждого элемента свой флажок «меня на этой итерации трогали». >[61] ob_kun (2008-07-08 17:36:00) >и откуда взялось ifItem?это переменная-итератор. в данном смысле конструкция foreach примерно так раскрывается:
var
a: array [1..10] of Integer;
item: Integer;
cnt: Integer;
…
for cnt := 0 to High(a) do
item := a[cnt];
….
end; >[62] ob_kun (2008-07-08 17:47:00) >А откуда ж тогда возьмутся необновленные?пришёл марсианец и украл один сетевой интерфейс. --- Do what thou wilt shall be the whole of the Law.
-
> у каждого элемента свой флажок «меня на этой итерации трогали».
а флажок этот как реализуется?
> это переменная-итератор.
а тип у нее какой? > пришёл марсианец и украл один сетевой интерфейс.
вот заразна душа)
-
> а флажок этот как реализуется?
неужто придется вводить доп лист, индексы которого соответствуют индексам в ListView?
-
>[64] ob_kun (2008-07-08 17:56:00) >а флажок этот как реализуется?как программист захочет. главное, чтобы с каждым элементом был чётко связан свой флажок. >а тип у нее какой?посмотри на мой код-расшифровку внимательно. >вот заразна душа)— Цан, извини, а вот такие, с хоботками, это кто? — спросил Гедеван.
— Никто. Фитюльки.
— В каком смысле?
— Во всех. Болтают, что они тут раньше, до плюкан жили. Но это так… Треп. --- All Your Base Are Belong to Us
-
>[65] ob_kun (2008-07-08 17:59:00) >неужто придется вводить доп лист, индексы которого соответствуют индексам в >ListView? у item есть чудное свойство data.
--- All Your Base Are Belong to Us
-
> посмотри на мой код-расшифровку внимательно.
такое чувство, что коли все типа Integer, а pIfTable типа PMibIfTable, то и ifItem должна быть типа PMibIfTable ))))
-
Свойство это типа Pointer, а как его припихнуть, на что сослаться - тоже вопрос....
a = 1; // отмечен lv.Items[0].Data := @a;
?
-
Или просто
lv.Items[0].Data := Pointer(1);
...
lv.Items[1].Data := Pointer(0);
?
-
>[70] ob_kun (2008-07-08 18:12:00) вот это мысль верная. %-)
>[68] ob_kun (2008-07-08 18:06:00) >такое чувство, что коли все типа Integer, а pIfTable типа PMibIfTable, то и ifItem >должна быть типа PMibIfTable )))) это потому, что в Delphi нет foreach. точнее, не было. %-) вот и непривычно. ничего, потом пригодится когда-нибудь.
--- Understanding is not required. Only obedience.
-
Так по поводу типа ifItem я верно угадал???
-
Я просто не совсем понимаю, как переложить аналогию с массивом на структуру.
-
>[73] ob_kun (2008-07-09 12:58:00) да пофигу. первый цикл у тебя верный, оставь тот псевдокод. я просто твой цикл короче переписал, потому что ленивый.
--- All Your Base Are Belong to Us
-
Ты имеешь ввиду, оставить for i := 0 to pIfTable.dwNumEntries-1 do begin ....
?
-
>[75] ob_kun (2008-07-09 14:01:00) угу. это и есть foreach, только выраженый более многословно. %-)
--- All Your Base Are Belong to Us
-
Завтра постараюсь написать процедуру в более-менее нормальном варианте. Остался еще вопрос - как ты представляешь себе, что суть процедура IsItemInList ? Как она должна осуществлять поиск элемента? По имени интерфейса (добавить отображение wszName) ?
-
>[77] ob_kun (2008-07-09 23:34:00) да хоть и так. или по адресу, например.
--- All Your Base Are Belong to Us
-
А есть какая-то возможность, чтобы поля в ListView были, но их не было видно? Или стоит просто писать в Tag у элементов первой колонки значение wszName?
-
>[79] ob_kun (2008-07-10 13:35:00) а зачем ты вообще к полям привязался? у тебя вон целый pointer на что угодно без дела простаивает.
--- All Your Base Are Belong to Us
-
Pointer идет для отметки. А для идентификации наличия такого элемента?!
-
Ау...
-
Или есть еще какой-то вариант?
-
>[83] ob_kun (2008-07-11 11:07:00) а что тут непонятного-то? поинтер, например, может указывать на структуру.
--- All Your Base Are Belong to Us
-
О! Точно, спасибо. Итак, я создаю
type TIdentStruct = packed record Flag : Byte; // как я понимаю, хватит для 0 и 1 ) Index : Integer; // решил использовать не wszName, а dwIndex end;
так?
-
> [84] ketmar © (13.07.08 00:35)
мальчик никогда не видел ассемблера, ему непонятно, как в 4 байта упихать целую структуру. Лучше напиши ему всю программу, будет гораздо проще и быстрее
-
>[86] wl © (2008-07-14 14:40:00) человек вполне поддаётся обучению, по моему. какой толк ему заклинания давать?
>[85] ob_kun (2008-07-14 14:18:00) можно и так. это не важно. указателю пофигу, на что указывать. %-)
--- All Your Base Are Belong to Us
-
> wl © (14.07.08 14:40) [86]
Вы правы, ассемблер я видел только в страшных промежутках программ asm...end; хотя о назначении JMP, JNZ и прочего я представление имею.... А по поводу полностью кода - это плохо, я сам хочу разбираться.
|