» Нажмите, для открытия спойлера | Press to open the spoiler «
Code
wchar_t *ReadString (FILE *file, wchar_t *Dest, int nDestLength, int nCodePage) { char *lpDest = (char*)xf_malloc ((nDestLength+1)*3); //UTF-8, up to 3 bytes per char support
Нужно сделать аналог функции на Delphi. Особенностью задачи является использование API и обязательный отказ от громоздких модулей типа SysUtils, в идеале нужно вообще оставить в uses только Windows. Прошу помощи.
yah, 26.08.2009 - 16:52
Если ты хочешь использовать API-функции, то никаких проблем, связанных с языком C++\Delphi, возникнуть не должно, т.к. API - он и в африке API. Если брать СИ-шные функии, то для них есть аналоги в Делфи: 1. "xf_malloc" - не встречался. Встречалась только функция malloc (если язык - С++, то куда уместнее было бы использовать new\delete для работы с памятью). Для Си-шного "malloc" есть делфи-аналоги GetMem/FreeMem, New/Dispose, либо SetLength/Finalize. 2. "memset" - можно использовать ZeroMemory. 3. Для работы с указателями вместо СИ-шных *\& используется делфи-аналоги ^\@.
Soloton, 27.08.2009 - 7:19
Цитата | Quote(yah @ 26.08.2009 - 16:52)
"xf_malloc" - не встречался.
Это оболочка для malloc, используется по всему коду, который перевожу, можно префикс xf_ опустить, смысл от этого не поменяется.
Собственно проблемы с fgets (). Что из Delphi-функций может быть использовано вместо неё? Пробовал так:
» Нажмите, для открытия спойлера | Press to open the spoiler «
Code
function ReadString (Afile: hFile; Dest: PChar; nDestLength, nCodePage: DWORD): PChar; var lpDest: PAnsiChar; nLength: integer; nNewLength: integer; begin GetMem(lpDest, (nDestLength+1)); FillMemory(lpDest, (nDestLength+1), 0); ReadFile(Afile, lpDest^, nDestLength, nDestLength, nil); if nDestLength <> 0 then begin MultiByteToWideChar(CP_OEMCP, 0, lpDest, nDestLength, Dest, nDestLength); end else begin FreeMem(lpDest); exit; end; FreeMem(lpDest); // <-- Тут AV GetMem(Result, nDestLength+1); lstrcpy(Result, Dest); lstrcat(Result, #0); end;
Получаю AV при попытке освобождения памяти. Если не использовать ReadFile, то всё нормально, правда тогда ф-я вообще ничего не читает.
yah, 27.08.2009 - 10:06
Цитата | Quote
function ReadString (Afile: hFile; Dest: PChar; nDestLength, nCodePage: DWORD): PChar; var lpDest: PAnsiChar; nLength: integer; nNewLength: integer; begin GetMem(lpDest, (nDestLength+1)); FillMemory(lpDest, (nDestLength+1), 0); ReadFile(Afile, lpDest^, nDestLength, nDestLength, nil); if nDestLength <> 0 then begin MultiByteToWideChar(CP_OEMCP, 0, lpDest, nDestLength, Dest, nDestLength); end else begin FreeMem(lpDest); - освободили память.... exit; end; FreeMem(lpDest); // <-- "Тут AV". Пытаемся освободить память, которую освободили ранее. Получаем AV. GetMem(Result, nDestLength+1); lstrcpy(Result, Dest); lstrcat(Result, #0); end;
stepanyk, 27.08.2009 - 10:48
yah, это тут не при чем:
» Нажмите, для открытия спойлера | Press to open the spoiler «
Code
function ReadString (Afile: hFile; Dest: PChar; nDestLength, nCodePage: DWORD): PChar; var lpDest: PAnsiChar; nLength: integer; nNewLength: integer; begin GetMem(lpDest, (nDestLength+1)); FillMemory(lpDest, (nDestLength+1), 0); ReadFile(Afile, lpDest^, nDestLength, nDestLength, nil); if nDestLength <> 0 then begin MultiByteToWideChar(CP_OEMCP, 0, lpDest, nDestLength, Dest, nDestLength); end else begin FreeMem(lpDest); //<- освободили память.... exit;//<-- прерывает функцию end; FreeMem(lpDest); // <-- "Тут AV". Сюда не доходит GetMem(Result, nDestLength+1); lstrcpy(Result, Dest); lstrcat(Result, #0); end;
а может попробовать CloseHandle сделать? Вдруг поможет:
» Нажмите, для открытия спойлера | Press to open the spoiler «
BOOL WINAPI ReadFile( __in HANDLE hFile, __out LPVOID lpBuffer, __in DWORD nNumberOfBytesToRead, __out_opt LPDWORD lpNumberOfBytesRead, __inout_opt LPOVERLAPPED lpOverlapped ); Как интересно ваш код сработает, если API-функция ReadFile возвращает совсем не хэндл файла? Я его в парамертрах к своей функции пишу, и закрываю вне функции.
yah, 27.08.2009 - 11:05
Цитата | Quote(stepanyk @ 27.08.2009 - 11:48)
это тут не при чем:
Тогда следует проверить функцию GetMem(lpDest, (nDestLength+1)). Может, по неизвестной причине, не происходит выделения памяти. Советы: 1. Смотреть в отладчике шаг GetMem(lpDest, (nDestLength+1)); 2. Посмотреть адрес, на который указывает указатель lpDest после вызова MultiByteToWideChar(CP_OEMCP, 0, lpDest, nDestLength, Dest, nDestLength); 3. Посмотреть адрес, на который указывает указатель lpDest до и после первого вызова FreeMem(lpDest); 4. Посмотреть адрес, на который указывает указатель lpDest до и после второго вызова FreeMem(lpDest); 5. "а может попробовать CloseHandle сделать? Вдруг поможет:"(с)