Страница 2 из 3
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 17:01:37
debi12345
Chunk.size
Где устанавлвивается это значение ? Какие значения для него показывает отладчик ?
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 17:12:47
vitaly_l
debi12345 писал(а):Где устанавлвивается это значение ? Какие значения для него показывает отладчик ?
1) Значения записаны в файле.
2) Они наверно идентифицируются правильно: 12, 54, 338, 1234254 и т.д.
Добавлено спустя 2 минуты 53 секунды:Дело не в Chunk.size, я заменил на единичку - всё равно падает.
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 17:32:57
debi12345
Где находится колбэк-функция ? В С-ой ДЛЛ ? Есть ее код ? Нужно пошагово в отладчике смотреть - что она делает в памяти.
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 17:55:44
vitaly_l
Никаких Dll нет.
Это выглядит вот так:
1) в шапке модуля:
TReadCallback = procedure(Chunk: TChunkRec; Data: Pointer); cdecl;
2) в функции: LoadFromStream(Stream: TStream;
ReadCallback: TReadCallback; UserData: Pointer): LongWord;
3) а это тело цикла while функции LoadFromStream:
Код: Выделить всё
Read(Chunk,8);
ReverseByteOrder(@Chunk.size,4);
StartPos:=Position;
GetMem(Chunk.data,Chunk.size);
Stream.Read(Chunk.data^,Chunk.size);
if Assigned(ReadCallback) //( if Assigned(ReadCallback) - работает нормально) в смысле Assigned...
then ReadCallback(Chunk,UserData); // <== а вот здесь модуль всегда падает... если закомментировать то проходит весь stream
FreeMem(Chunk.data,Chunk.size);
Position:=StartPos+Chunk.size+(StartPos+Chunk.size) mod 2;
.
Добавлено спустя 18 минут 9 секунд:В модуле в параллельной функции:
в разделе public, можно получить:
1)
property Data: Pointer read FData;2)
property Size: LongWord read FSize;
Как мне дешифровать содержимое Data, чтобы поместить в TMemo? 
вот так? ==> побайтово конвертирвать "Byte((data+i)^)" в "char"?
.
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 18:07:59
debi12345
Никаких Dll нет.
А зачем тогда понадобилось CDECL ?
Как мне дешифровать содержимое Data,
Сперва нужно его просто получить в память - без вылета из программы

И потом уже дешифровать.
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 18:17:53
vitaly_l
debi12345 писал(а):А зачем тогда понадобилось CDECL ?
CDECL - это что вызов функции из dll? .. тогда это какая-то стандартная dll...
А может это быть не Dll? а какой нить код, который размещён в соседнем модуле?debi12345 писал(а):Сперва нужно его просто получить в память - без вылета из программы
В модуле два варианта загрузки файла. Один я починил и он загружает файл и заносит данные в FData,
соответственно FDATA - можно прочитать.
А второй вариант загрузки это то что приведено в примерах в данном топике.
Я хотел восстановить второй вариант, т.к. модуль подключается параллельно с 10 идентичными модулями и отвечает за определённое расширение. Но он при подключении валится. Я думаю что сбой во второй функции т.к. первая работает. И там проследить по коду не получается, т.к. Ctrl+клик ведёт в тупик.
Но я могу ещё попробовать забить данные в программу, минуя "стандартный загрузчик", который используют остальные модули(отвечающие за другие расширения), для этого нужно дешифровать FData: Pointer. А я никогда этого не делал... Вроде всё понимаю... а как это делается не знаю

Знаний и опыта - не хватает
Как мне дешифровать содержимое FData : Pointer?
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 19:52:28
debi12345
заносит данные в FData,
соответственно FDATA - можно прочитать.
Что показывает отладчик ? В структуре сидят правильные данные ? Размеры в порядке ? Такие вещи делаются имено в отладчике

для этого нужно дешифровать FData: Pointer.
Какими байтами в в этом пойнтере предствалено например число 123.45 ? Нужно ли вызывать Int(Float)ToStr Или достаточно посимвольной конкатенации ?
По ID типа выбрать нужный декодировщик - Int(Float)ToStr,.. и передать ему
А я никогда этого не делал... Вроде всё понимаю... а как это делается не знаю Знаний и опыта - не хватает
И замахнулись на нестандртные деккларации

А может это быть не Dll? а какой нить код, который размещён в соседнем модуле
С точки зрения применимости в FPC:
CDECL - нужно для обращения к DLL, написаным на С
STDCALL (помесь CDECL & PASCAL) - нужно для обращения к DLL, представляющим win32 API.
Все остальное - PASCAL (по умолчанию).
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 20:13:24
bormant
vitaly_l,
у вас LoadFromStream() читает из файла порцию данных (chunk); затем вызывает вашу функцию, передавая ей по значению считанные данные и ваш же пользовательский указатель; затем освобождает память. Всё это повторяется, пока не закончится файл (скорее всего, этот код вы не приводили).
Как интерпретировать считанные данные, дело сугубо ваше, этот вопрос находится за пределами описанного алгоритма.
От вас требуется реализовать что-то вроде:
procedure MyHandler(Chunk: TChunkRec; Data: TMemo); cdecl;
begin
// в Data будем получать указатель на TMemo
// ... как-то обрабатываем Chunk
Data.Lines.Add( "какие-то данные" );
end;
чтобы потом передать в вызов
Readed := LoadFromStream(Stream, @MyHandler, Memo1);
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 20:29:35
vitaly_l
debi12345 писал(а):Такие вещи делаются именно в отладчике
Я не Земной программист, а инопланетянин - для меня отладчиком является TMemo...
Что Вы называете отладчиком? В Лазарусе есть только кнопка "сбросить отладчик"...
debi12345 писал(а):Какими байтами в в этом пойнтере предствалено например число 123.45 ? Нужно ли вызывать Int(Float)ToStr Или достаточно посимвольной конкатенации ?
Да хоть как нибудь вывести бы - этот чёртов стэк...
Как только я смогу получить содержимое в любом понятном для меня виде например array of string, мне этого будет достаточно.
debi12345 писал(а):И замахнулись на нестандртные деккларации
Я ни на что не замахивался... это не мой код... я просто никогда не пользовался стэками, мне для моих задач хватало array. Хотя стэк наверно быстрее.
debi12345 писал(а):CDECL - нужно для обращения к DLL, написаным на С
Там точно нет никакой Dll - это из GLScene, открытый код.
bormant писал(а):чтобы потом передать в вызов
Readed := LoadFromStream(Stream, @MyHandler, Memo1);
Тобишь заменить на свою функцию типа MyHandler... Такого быть не может... остальные расширения грузятся без dll и без моей функции... Либо эта функция априори нерабочая и не участвует в загрузке, а работает только вторая.
Кстати!... Посмотрю как в других модулях организован LoadFromStream... Может там есть...?
bormant писал(а):... как-то обрабатываем Chunk
Вот это я и хочу понять... как его нужно обработать... чтобы переместить данные в нужный мне буфер... но у меня не получается получить данные в понятном мне виде... вот... нажаловался...
.
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 20:44:18
bormant
vitaly_l писал(а):у меня не получается получить данные в понятном мне виде
Это не на форуме, это в документации по формату файла искать надо, как данные того или иного чанка интерпретировать.
В качестве минимально понятного формата могу предложить 16-ричный дамп.
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 20:59:31
vitaly_l
bormant писал(а):это в документации по формату файла искать надо
Я её как раз только прочитал... там только общие поверхностные данные...
типа: Load функция для загрузки... Clear функция для очистки... итп...
Коротеч, грязная вода есть... а самого необходимого как всегда нет...
Добавлено спустя 1 минуту 30 секунд:Неужели нет никакого стандартного метода интерпретировать содержимое data : pointer из стэка?
/
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 21:02:32
debi12345
Да хоть как нибудь вывести бы - этот чёртов стэк...
1) на "падающей" функции назначить точку остнова
2) как остановится - выпонять прграмму пошагово, глядя в содержимое памяти
Как в Лазарусе смортеть в память из отлдачика в формате исходой структуры (название переменной = ее значение) - не помню (пользуюсь MSE*), но 100% это есть.
Неужели нет никакого стандартного метода интерпретировать содержимое data : pointer из stream?
Есть - у компонента "TArtificialIntellectLikeHumanStream".
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 21:21:54
vitaly_l
Добавлено спустя 55 секунд:debi12345 писал(а):1) на "падающей" функции назначить точку остнова
2) как остановится - выпонять прграмму пошагово, глядя в содержимое памяти
Хождение по коду ассемблера Вы называете отладчиком?
Там два перехода: со входом и в обход... И даже с учётом того что я понимаю 10-20% из ассемблерного кода,
я твёрдо уверен что, найти в ассемблере ошибку... Для меня сверх сложная задача... Чтобы читать ассемблер нужно в нём жить...
Мне проще новый язык для машинного кода придумать нежели читать и понимать ассемблер.
bormant писал(а):Это не на форуме, это в документации по формату файла искать надо, как данные того или иного чанка интерпретировать.
А можно их все интерпретировать в string? Мне нужно понять схему считывания из стэка.
.
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 21:30:44
bormant
vitaly_l писал(а):Мне нужно понять схему считывания из стэка.
Не нужно. Вам содержимое чанка приходит готовое, размер в Size, данные в Data^.
А вот что с данными делать, как их интерпретировать -- это читайте в документации на формат.
Вот вам упрощённый пример использования методики с обратным вызовом (и даже с тем же соглашением о вызове -- cdecl):
Исходные данные (tst.txt):
Код: Выделить всё
1
Это фрагмент 1 из 1 строки
2
Это фрагмент 2
из 2 строк
3
Это фрагмент 3
из 3
строк
1
Это фрагмент 4 из 1 строки
Исходный код:
Код: Выделить всё
// это нам дано
const
EOL = #13#10;
type
PChunkRec = ^TChunkRec;
TChunkRec = record
Size: integer;
Data: pointer;
end;
TReadCallback = procedure(Chunk: TChunkRec; Data: Pointer); cdecl;
procedure LoadFromFile(var F: text; ReadCallback: TReadCallback; UserData: Pointer);
var
Chunk: TChunkRec;
s, l: string;
i, n: integer;
begin
while not SeekEof(F) do with Chunk do begin
ReadLn(F, n); s := '';
for i := n downto 1 do begin ReadLn(F, l); s := s + l + EOL; end;
Size := Length(s) + 1; GetMem(Data, Size);
Move(s[1], Data^, Size - 1); (PChar(Data) + Size - 1)^ := #0;
if ReadCallback <> nil then ReadCallback(Chunk, UserData);
FreeMem(Data);
end;
end;
// это дописываем мы для работы LoadFromFile
procedure MyHandler(Chunk: TChunkRec; UserData: Pointer); cdecl;
begin
with Chunk do WriteLn(Size, EOL, PChar(Data));
end;
var
f: text;
begin
Assign(f, 'tst.txt'); Reset(f);
LoadFromFile(f, @MyHandler, nil);
Close(f);
end.
Прогон:
Код: Выделить всё
29
Это фрагмент 1 из 1 строки
29
Это фрагмент 2
из 2 строк
30
Это фрагмент 3
из 3
строк
29
Это фрагмент 4 из 1 строки
Надеюсь, так технология понятнее стала?
Re: cdecl - как это работает и для чего это?
Добавлено: 24.03.2013 22:13:54
vitaly_l
bormant писал(а):Надеюсь, так технология понятнее стала?
Да, так немного прозрение наблюдается...
По крайней мере это код, который можно увидеть и
интерпретировать на мой инопланетянский язык программирования.
90% мне понятно - остальное допойму в процессе.
Спасибо...
.
Добавлено спустя 20 минут 40 секунд:Move(s[1], Data^, Size - 1); <== вот здесь непонятно почему
s[1]??? А просто
s почему нельзя? Зачем
[1]???
(PChar(Data) + Size - 1)^ := #0; <== вот этот код, не понимаю, что делает?

Если несложно, буквально в двух словах, разъясните - пожалуйста.
.