:: Не фоксом единым
Delphi передача файла в dll
binom

Сообщений: 35
Откуда: Йошкар-Ола
Дата регистрации: 23.09.2010
Возникла необходимость передать jpg-файл в dll (Delphi) для дальнейшей обработки
на стороне фокса:
s1 = filetostr('c:\Delphi\Image2\Im\image2.jpg')
DECLARE STRING Buffers IN c:\delphi\image2\image2.dll string @s1
? Buffers(s1)
CLEAR DLLS

На стороне Delphi
library Image2;
function Buffers(Stroka:PChar):Pchar;stdcall;
var
Res:PChar;
Dest: TFileStream;
begin
Res:= PChar(Stroka);
Dest:= TFileStream.Create('c:\delphi\image2\im\image3.jpg', fmCreate or fmShareExclusive);
try
Dest.WriteBuffer(Res,SIZEof(Res));
finally
FreeAndNil(Dest);
end;
Result:=PChar('Ok');
end;
exports Buffers;

Файл создается, но размером всего 4 байта, где-то я накосячил, не могу понять где, помогите разобраться.
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
Передать "файл" никак нельзя. Так говорить - терминологическая ошибка. Можно передать имя файла, можно передать какой-то низкоуровневый "хендл" к открытому файлу (но так делать не стоит), можно передать содержимое файла. Собственно говоря ты именно это и пытаешься сделать.
Тип PChar это просто указатель, адрес в памяти - его размер будет равен 4 байта для 32-битных систем и 8 байт для 64-битных.
Если бы ты передавал строку, то формальным признаком её завершения по сишному соглашению является байт с кодом 0 (CHR(0)) - собственно говоря именно так и работает со строками классический си. Однако ты передаешь не "текст", и в содержимом jpeg файла наверняка встретится не один нулевой байт. Поэтому вызывающая сторона должна ЯВНО передать "размер буфера". Ну а принимающая уже ориентироваться на этот размер... Хотя, конечно, это тоже небезопасный вариант, ну да АПИ функции обычно так работают... Добавь только АДЕКВАТНЫЙ обработчик ошибок (а не заглушку, которая их тупо игнорирует).
Возвращать, кстати, следует не строку, а число - код завершения. Т.к. передавая PChar ты просто передаешь адрес буфера СОЗДАННОГО И УПРАВЛЯЕМОГО дельфовым компонентом, в памяти управляемой дельфи. И кто его будет освобождать? Фокс никак не сможет, а городить ещё одну функцию для того чтобы освободить место занятое этой возвращённой строкой... Ну так не делают. Даже если возвращать нужно именно строку, а не тривиальный код успеха/ошибки.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
binom

Сообщений: 35
Откуда: Йошкар-Ола
Дата регистрации: 23.09.2010
Да, конечно же нужно передать содержимое файла, про освобождение памяти не учел. Может быть попробовать использовать bitmap? Только не знаю сможет ли Delphi прочесть bitmap, созданный в Фоксе?
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
Ещё раз по простому:
1) Передавать содержимое так же, через "строку", которая на самом деле массив байт, и внутри могут быть и CHR(0) которые не "признак конца строки". НЕ освобождать в дельфи эту память.
2) Добавить параметр "размер буфера данных" - т.к. других способов получить "где заканчивается" PChar с "не текстом" нет.
3) Возвращать тривиальное число.

Можно сделать альтернативно - передавать в качестве параметра просто имя файла. Тогда можно размер строки и не передавать, а вместо этого через StrLen его рассчитывать - эта функция ищет нуль-терминатор, а такой символ не должен встречаться в "нормальных" именах/путях файлов.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
binom

Сообщений: 35
Откуда: Йошкар-Ола
Дата регистрации: 23.09.2010
А если так:
SET COMPATIBLE ON
s1 = filetostr('c:\Delphi\Image2\Im\image2.jpg')
s2 = FSIZE('c:\Delphi\Image2\Im\image2.jpg')
SET COMPATIBLE OFF
DECLARE STRING Buffers IN c:\delphi\image2\image2.dll string @s1, integer @s2
? Buffers(s1,s2)
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
LEN(m.s1) вполне достаточно - прямо в вызове АПИ. На кой чёрт там FSIZE то сдался

@ тоже не нужны - "строка" передаётся только В функцию (обратно не принимается). Число тем более предаётся как число, а не как ссылка на число. Ну и возвращаемое значение не STRING а INTEGER.

Соответственно в дельфи сигнатура функции:

function Buffers(ImageBinary:PChar; ImageBinaryLen: Integer): Integer; stdcall;


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Божья_коровка

Сообщений: 25720
Дата регистрации: 23.08.2001
У меня в фоксе -
IF FILE(_cur_dir+'\photo.dll')
Declare getphoto IN photo.dll string, string, integer
ENDIF

Ну и потом getphoto(pathtotmp,_source_vu,vu_res.nn)

pathtotmp путь до файлас его именем, _source_vu - табличка оракловая где описание к файлу,vu_res.nn -айдишник записи

Вот код на стороне дельфи приложить не могу, исходников на эту дллку нет


------------------
Жись, она как зёбра, полоса белая, полоса черная, а мне всегда задница достается...




Исправлено 1 раз(а). Последнее : Божья_коровка, 30.05.17 19:32
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
binom

Сообщений: 35
Откуда: Йошкар-Ола
Дата регистрации: 23.09.2010
Сделал в фоксе:
s1 = filetostr('c:\Delphi\Image2\Im\image2.jpg')
s2 = LEN(m.s1)
DECLARE INTEGER Buffers IN c:\delphi\image2\image2.dll string s1, integer s2
? Buffers(s1,s2)

в delphi
function Buffers(ImageBinary:PChar; ImageBinaryLen:Integer): Integer; stdcall;
var
Res:PChar;
ResSize:Integer;
Dest: TFileStream;
begin
Res:= PChar(ImageBinary);
ResSize:= Integer(ImageBinaryLen);
Dest := TFileStream.Create('c:\delphi\image2\im\image3.jpg', fmCreate or fmShareExclusive);
try
Dest.WriteBuffer(Res,ResSize);
finally
FreeAndNil(Dest);
end;
Result := ResSize;
end;
exports Buffers;

Фокс выдает ошибку Declare DLL call caused an exception
(неверный тип передаваемой переменной)
Что сделать?
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Аспид

Сообщений: 3475
Откуда: Москва
Дата регистрации: 01.04.2005
Вот мельком глянул. Но...
Что вы передаете в вызове?
binom
DECLARE INTEGER Buffers IN c:\delphi\image2\image2.dll string s1, integer s2
string и integer
чего ждет функция?
function Buffers(ImageBinary:PChar; ImageBinaryLen:Integer

Т.е. 1й параметр явно не тот.
Должен быть указатель.
Игорь же, все в самом начале разжевал.

Более того, бегло глянув на код, не ясно, на фига козе баян?
У вас в дельфях строка
binom
Dest := TFileStream.Create('c:\delphi\image2\im\image3.jpg', fmCreate or fmShareExclusive);
Это как оценивать?

Кажется вы в серьезной путанице.
Выбросьте указатели, и передавайте имя файла.
Мне кажется вам проще будет разобраться.


------------------




Исправлено 1 раз(а). Последнее : Аспид, 31.05.17 07:32
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
binom
Сделал в фоксе:
s1 = filetostr('c:\Delphi\Image2\Im\image2.jpg')
s2 = LEN(m.s1)
DECLARE INTEGER Buffers IN c:\delphi\image2\image2.dll string s1, integer s2
? Buffers(s1,s2)
Это пойдёт.
binom
в delphi
function Buffers(ImageBinary:PChar; ImageBinaryLen:Integer): Integer; stdcall;
var
Res:PChar;
ResSize:Integer;
Dest: TFileStream;
begin
Res:= PChar(ImageBinary);
ResSize:= Integer(ImageBinaryLen); Зачем? У нас и так уже PChar и Integer - смысл пытаться преобразовывать их сами в себя. При том я совершенно не уверен что PChar МОЖНО преобразовать в PChar.
Dest := TFileStream.Create('c:\delphi\image2\im\image3.jpg', fmCreate or fmShareExclusive);
try
Dest.WriteBuffer(Res,ResSize); Тут по идее должны быть ImageBinary, ImageBinaryLen
finally
FreeAndNil(Dest);
end;
Result := ResSize; Возвращать нужно признак успешности работы функции, а не "размер буфера для записи" который тупо передан снаружи.
end;
exports Buffers;
И вообще я не спец по дельфи - возможно с его стороны первый параметр функции вообще надо описывать как PByte или даже Pointer, чтобы уж гарантированно работать с буфером как с массивом байт, а не "символов" которые дельфи может трактовать по своему, как и фокс...

binom
Фокс выдает ошибку Declare DLL call caused an exception
(неверный тип передаваемой переменной)
Что сделать?
Вообще-то ошибка говорит вовсе не про "неверный тип" - она вполне недвусмысленно сообщает о том что внутри твоей dll произошло исключение.
Нужно либо осваивать дельфи самостоятельно, либо попросить помощи у тех кто им хорошо владеет, ну или хотя-бы работает с той же версией с которой работаешь ты


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
Аспид
Т.е. 1й параметр явно не тот.
Должен быть указатель.
PChar это и есть указатель. И именно "на строку". Точнее он "указатель на символ", но может трактоваться и как указатель на массив символов, а это уже и есть "строка". Правда не в дельфовском понятии String, т.к. там это "строка с обвесами".
Аспид
У вас в дельфях строка
binom
Dest := TFileStream.Create('c:\delphi\image2\im\image3.jpg', fmCreate or fmShareExclusive);
Это как оценивать?
Это просто создаётся "выходной файл" с фиксированным именем, куда автор и пытается записать данные. Имя файла другое.
Аспид
Выбросьте указатели, и передавайте имя файла.
Мне кажется вам проще будет разобраться.
Не проще, т.к. никаких таких "строк" в парадигме АПИ вызовов нет. Дельфовская строка нигде кроме как в дельфи применяться не может - для взаимодействия с другими системами как раз и приходится применять "сишную строку", которая по сути просто указатель и есть - т.е. адрес ячейки памяти, где начинается соответствующая строка... А это и есть PChar, PAnsiChar, PWideChar или же более низкоуровневый Pointer... Есть ещё OLE строки которые BSTR, но тут я не в курсе как с ними корректно работать в дельфях, а автор вопроса и подавно не разберётся, т.к. запутался уже в первых 3 соснах
Т.е. даже если бы он передавал "имя файла" а не его содержимое, то ему пришлось бы его описывать в параметрах функции как PChar, и потом уже конвертировать для дальнейшей работы в String.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
binom

Сообщений: 35
Откуда: Йошкар-Ола
Дата регистрации: 23.09.2010
Как всегда хотел сделать красиво - передать в dll delphi содержимое файла, а оказывается нельзя, но очень хочется. Передавать имя файла это просто:
код на фоксе
s1 = 'c:\Delphi\Image2\Im\image2.jpg'
DECLARE String Buffers IN c:\delphi\image2\image2.dll string s1
? Buffers(s1)
CLEAR DLLS

код на делфи:
function Buffers(Stroka:PChar):PChar;stdcall;
var
Source: TFileStream;
Dest: TFileStream;
begin
Source := TFileStream.Create(Stroka, fmOpenRead or fmShareDenyWrite);
Dest := TFileStream.Create('c:\delphi\image2\im\image3.jpg', fmCreate or fmShareExclusive);
try
Dest.CopyFrom(Source, Source.Size);
finally
FreeAndNil(Dest);
end;
finally
FreeAndNil(Source);
end;
Result:=PChar('Ok');

А если попробовать использовать буфер обмена Clipboard, будет ли читать из буфера делфи файл, записанный в буфер в среде foxpro?
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
binom
передать в dll delphi содержимое файла, а оказывается нельзя
Можно. Если всё аккуратно и с пониманием сути используемых типов и методов делать.
binom
А если попробовать использовать буфер обмена Clipboard, будет ли читать из буфера делфи файл, записанный в буфер в среде foxpro?
Смотря ЧТО и смотря КАК туда записано. Боюсь что положить картинку в буфер обмена на стороне фокса ты не сможешь, раз уж с таким несложным в принципе приёмом как передача строки-буфера возникают непонятки...
P.S. Ещё раз обращаю внимание - передавать из Delphi куда бы то ни было строку созданную в Delphi - потенциально небезопасно. Это КАК МИНИМУМ вызовет утечку памяти, а может и полноценные "вылеты" вызывать.
P.P.S. Просто хрен его знает чего принимает в качестве первого параметра метод WriteBuffer, и как он это интерпретирует (за что мне паскаль всегда меньше си нравился - он слишком много "додумывает" за программиста в таких ситуациях). В си если есть указатель, то метод принимающий void* это метод принимающий указатель. А тут понять невозможно - принимает "что угодно", а как он это понимает внутри... Может быть нужно при передаче в качестве параметра разыменовывать эту переменную, т.е. писать не просто ImageBinary, а ImageBinary^
Это всё можно было бы выяснить за 5 минут имея нужную IDE и тривиально запустив эту dll под отладчиком (надеюсь дельфи умеет присоединять свой отладчик к чужим процессам для отладки такого рода взаимодействия с dll), или банально попробовав вариант с разыменованием и без.


------------------
WBR, Igor




Исправлено 1 раз(а). Последнее : Igor Korolyov, 31.05.17 21:58
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
binom

Сообщений: 35
Откуда: Йошкар-Ола
Дата регистрации: 23.09.2010
При передаче из фокса в получаемом Delhpi буфере непонятно что. Решил проблему с помощью декодирования файла в base64:
fox:
s1 = filetostr('c:\Delphi\Image2\Im\image2.jpg')
s3 = STRCONV(s1,13)
DECLARE String Buffers IN c:\delphi\image2\image2.dll string s3
? Buffers(s3)
CLEAR DLLS

delphi:
function Buffers(Stroka:PChar):PChar;stdcall;
var
Fs : TFileStream;
S : AnsiString;
begin
Fs := TFileStream.Create('c:\delphi\image2\im\image4.jpg', fmCreate);
S := DecodeString(Trim(Stroka));
try
Fs.Write(S[1], Length(S));
finally
FreeAndNil(Fs);
end;

Смущает только то, что при этом возникают временные затраты на кодирование и раскодирование файла.
Ratings: 0 negative/0 positive
Re: Delphi передача файла в dll
Igor Korolyov
Автор

Сообщений: 34580
Дата регистрации: 28.05.2002
binom
При передаче из фокса в получаемом Delhpi буфере непонятно что.
Ну так надо было проанализировать что же это такое "непонятное". PChar несколько "синтетический" тип - он в новых (юникодных) версиях дельфей по идее отражается в PWideChar, а это уже никак не "набор байт".

Кроме того по своей сути это всё-же "символьный" тип - потому я и говорил что лучше смотреть в сторону "безтипового" Pointer или PByte - т.к. вполне возможно что использование "строки" будет сопровождаться либо перекодировками, либо неявными "усечениями" строки по достижении chr(0) или двойного chr(0).

В си это точно должен был бы быть void*

P.S. Как вижу, много раз повторённый совет НЕ использовать строку в качеству выходного значения пропал втуне...


------------------
WBR, Igor




Исправлено 1 раз(а). Последнее : Igor Korolyov, 08.06.17 14:24
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 5 (Гостей: 5)

© 2000-2024 Fox Club 
Яндекс.Метрика