Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (до версии 2009) - часть 5

Автор: Wahnsinn
Дата сообщения: 15.04.2010 19:21
на какой тип заменить один из параметров функции из сишной dll ..., byte **data, ... при вызове ее из delphi, из описания: data - содержит id созданного документа.
Автор: akaGM
Дата сообщения: 15.04.2010 20:28
Wahnsinn
лучше бы ты оригинальный хидер здесь привёл...
ну а навскидку:

bla_bla_bla(var data: pointer);

или:

type
PDOCID = ^Byte;
bla_bla_bla(var data: PDOCID);
Автор: Odysseos
Дата сообщения: 15.04.2010 20:52
Wahnsinn

Две звездочки - "указатель-на-указатель", но для Delphi правильней будет var data: PByteArray (если через этот параметр функция только получает данные - то const data: PByteArray, если только возвращает - то out data: PByteArray), где PByteArray = ^TByteArray; TByteArray = array [0 .. 0] of Byte;


akaGM

Параметр byte ** (или int **, или что угодно еще) функции в C - это, как правило, указатель-на-указатель не на отдельное значение соответствующего типа, а на массив элементов соотв. типа, длина для которого задается соседним параметром (ну или определенным значением внутри массива - как в случае со строками).
Автор: akaGM
Дата сообщения: 15.04.2010 21:01
Odysseos
я не телепат, поэтому и прошу хидер...

Цитата:
data - содержит id созданного документа.

и где здесь сказано, что это массив?
как правило, id -- это число, не более того...

и вообще, вот так будет правильнее:

Код: {$R-}
TByteArray = array[0..0] of Byte;
Автор: Wahnsinn
Дата сообщения: 15.04.2010 21:24
вот полная функция

Код:
DWORD __stdcall ScanEx(HWND hwndParent,
DWORD flags, char *scanType,
char *taskType,
DWORD docType, DWORD urgency,
char *params,
char *ip,
DWORD * count, byte*** images,
DWORD ** lengths, char ***filenames,
byte **data, DWORD *datalen,
char * msg);

flags = 0,
docType, urgency - 0
params = null
count, images, lengths = NULL, filanmes = NULL,
data - содержит id созданного документа
datalen - содержит длину поля data.
Автор: Odysseos
Дата сообщения: 15.04.2010 22:18
akaGM
Wahnsinn

Как я и предполагал:


Цитата:

byte **data, DWORD *datalen,


Это будет


Код:
out data: PByteArray; out datalen: Cardinal;
Автор: Wahnsinn
Дата сообщения: 15.04.2010 23:49
Odysseos
akaGM
ok, спасибо всем, собственно тест будет завтра удаленно, но с другими их функциями до этого все было нормально, думаю в этот раз тоже гладко пройдет.
Автор: akaGM
Дата сообщения: 16.04.2010 12:23
Odysseos

Цитата:
Мало того - я ни разу не встречал, чтоб кто-то где-то его включал.

с законами Мэрфи знаком?
если есть хоть малейшая дырка, она обязательно себя проявит
на личном, так сказать, опыте...
Автор: aspis
Дата сообщения: 16.04.2010 19:41

Цитата:
Контроль границ массива по умолчанию выключен. Мало того - я ни разу не встречал, чтоб кто-то где-то его включал.

В отладочной версии обязательно включаю.


Цитата:
если есть хоть малейшая дырка, она обязательно себя проявит
на личном, так сказать, опыте...

Присоединяюсь. Выскакивала ошибка доступа к памяти (EAccessViolation), причина которой был как раз выход за пределы массива.
Автор: Man_Without_Face
Дата сообщения: 19.04.2010 16:41
Подскажите пож, что не так делаю: есть Dll и exe. Вызываю отчеты из Dll (на форме в Dll, кот не показываю лежат компоненты frx). Нужно создать еще одну форму, в кот будут вводиться параметры для одного отчета. Передаю handle как и в той форме, но что то не то. Exe: [more]
public
handle : Thandle; //Хендл dll { Public declarations }
end;

var

frmMain: TfrmMain;

PlugExec : Procedure (appHandle: Thandle; msAliasName, msUser, msPassword : pChar); stdcall; //Объявление функции, которая будет выполнять плугин
PlugDel : Procedure; stdcall;

report1: procedure (appHandle: Thandle; b:double); stdcall; //
report2: procedure (date_begin, date_end :tdate); stdcall;

msAliasName, msUser, msPassword : string;
implementation
{$R *.dfm}


procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
@PlugDel := GetProcAddress(handle,'PluginDel');
try
Plugdel;
except
on e: Exception do
MessageDlg('Ошибка при выгрузке bbc5_reports.dll: '+PChar(E.Message), mtError, [mbOK],0);
end;

Action := caFree;
Release;
frmMain := nil;
end;

procedure TfrmMain.FormShow(Sender: TObject);
begin
if not FileExists('bbc5_reports.dll') then
MessageDlg('Нет файла bbc5_reports.dll', mtError, [mbOK], 0);
handle := LoadLibrary('bbc5_reports.dll'); //Загружаем dll
try
if handle <>0 then //Если всё в порядке, то идём дальше
begin
//Загружаем функцию загрузки
@PlugExec := GetProcAddress(handle,'PluginExec');
try
msAliasName := '';
msUser := '';
msPassword := '';

PlugExec(application.handle, pChar(msAliasName), pChar(msUser), pChar(msPassword));
except
on e: Exception do
MessageDlg('Не могу соединиться с базой: ' + PChar(E.Message), mtError, [mbOK],0);
end;
end;
except
MessageDlg('Ошибка загрузки bbc5_reports.dll', mtError, [mbOK], 0);
end;
end;
////////////////////////////////////////////////////////////////////////////////
//Здесь вызвать нужно форму в кот будут вводиться параметры:
procedure TfrmMain.cxButton1Click(Sender: TObject);
begin
@report1 := GetProcAddress(handle,'repOtherOborots');
try
report1(application.handle, cxDateEdit1.Date);
except
on e: Exception do
MessageDlg('Не могу передать параметры в bbc5_reports.dll. Ошибка: '+PChar(E.Message), mtError, [mbOK],0);
end;
end;
///////////////////////////////////////////////////////////////////////////////

procedure TfrmMain.cxButton2Click(Sender: TObject);
begin
@report2 := GetProcAddress(handle, 'repReceivedFiles');
try
report2(cxDateEdit2.Date, cxDateEdit1.Date);
except
on e: Exception do
MessageDlg('Не могу передать параметры в bbc5_reports.dll. Ошибка: '+PChar(E.Message), mtError, [mbOK],0);
end;
end;[/more]
Dll: [more]
library bbc5_reports;

uses
SysUtils,
forms,
Classes,
db,
dialogs,
uReports in 'uReports.pas' {frmReports},
uOborotka in 'Units\uOborotka.pas' {frmOborotka};

var Width, Height : integer; //Ширина, высота и позиция окна отчета
Position :tposition ;
{$R *.res}
procedure PluginExec(AppHandle:THandle; msAliasName, msUser, msPassword : pChar); stdcall;
begin //Процедура подключения Dll
try
Application.Handle:=AppHandle;
frmReports := TfrmReports.Create(nil);
except
on e: Exception do ShowMessage('Ошибка при загрузке формы отчетов: '+E.message);
end;
try //Передаю параметры из меин для соединения с базой
frmReports.dbDll.Close;
frmReports.dbDll.AliasName:=strPas(msAliasName);
frmReports.dbDll.Params.Values['USER NAME']:=strPas(msUser);
frmReports.dbDll.Params.Values['PASSWORD']:=strPas(msPassword);
except
on e: Exception do ShowMessage('Ошибка передачи параметров для соединения с базой: '+E.message);
end;

try
frmReports.dbDll.Open;
except
on e: Exception do ShowMessage('Ошибка соединения с базой: '+E.message);
end;

try
Width := 1280;
Height := 780;
Position := poScreenCenter;
except
on e: Exception do ShowMessage('Ошибка передачи параметров размера формы: '+E.message);
end;
end;

procedure PluginDel; stdcall; //Процедура выгрузки Dll
begin
try
FreeAndNil(frmReports);
Application.Handle:=0;
Except
on e: Exception do ShowMessage('Ошибка выгрузки Dll: '+E.message);
end;
end;

//////////////////////////////////////////////////////////////////////////////////////////////////////
procedure repReceivedFiles(begin_date, end_date :tdate); stdcall;
begin //Реестр принятых файлов
try
frmReports.repReceivedFiles.Variables.Clear;
frmReports.repReceivedFiles.Script.Variables['begin_date'] := FormatDateTime('yyyy-mm-dd',begin_date);
frmReports.repReceivedFiles.Script.Variables['end_date'] := FormatDateTime('yyyy-mm-dd',end_date);
frmReports.repReceivedFiles.Script.Variables['dateB_view'] := datetostr(begin_date);
frmReports.repReceivedFiles.Script.Variables['dateE_view'] := datetostr(end_date);
frmReports.repReceivedFiles.showreport();
frmReports.repReceivedFiles.PreviewForm.Width := Width;
frmReports.repReceivedFiles.PreviewForm.Height := Height;
frmReports.repReceivedFiles.PreviewForm.Position := Position;
Except
on e: Exception do ShowMessage('Ошибка загрузки отчета: '+E.message+' Проверьте внесенные данные');
end;
end;

procedure repOtherOborots(AppHandle:THandle; end_date :tdate); stdcall;
begin //Реестр принятых файлов
try

Application.Handle:=AppHandle; //Как здесь
frmOborotka := frmOborotka.Create(Application); //правильно
try
frmOborotka.Showmodal; //загрузить форму?
finally
frmOborotka.Free;
end;
Except
on e: Exception do ShowMessage('Ошибка загрузки отчета: '+E.message+' Проверьте внесенные данные');
end;
end;

//Экспортируемые функции
exports PluginExec, PluginDel, repClientsAll, repClientsWork, repClientsNotWork,
repNoResident, repClientsDeleted, repReceivedFiles, repOtherOborots;

begin
end.
[/more]
Автор: AviDen
Дата сообщения: 19.04.2010 18:09
Так а в чём, собственно, вопрос?
Автор: Frodo_Torbins
Дата сообщения: 19.04.2010 18:50
Man_Without_Face
Обычно в таких случаях помогает включение рантайм-пакетов.
Автор: AviDen
Дата сообщения: 19.04.2010 19:16
Frodo_Torbins, не сбивайте человека с мысли, мы ему уже и так две страницы объясняли разницу между BPL и DLL, если он теперь захочет от DLL уйти, придётся всё по новой повторять...
Автор: Frodo_Torbins
Дата сообщения: 19.04.2010 20:28
AviDen
Какая разница BPL или DLL? Пусть и для Dll и для Exe зайдет в "Project" -> "Options" -> "Packages" и поставит галку "Build with runtime packages". И все, его проблема будет решена (при условии что для Dll и Exe используется одна версия делфи/билдера).
Автор: AlexIntegral
Дата сообщения: 19.04.2010 21:35
Подскажите пожалуйста, можно ли в цикле, скажем for, сделать паузу? И как это можно реализовать. (кроме break и continue)
Автор: Frodo_Torbins
Дата сообщения: 19.04.2010 22:04
AlexIntegral
Либо Sleep(n{секунд}*1000), либо [more=так]
Код: [no]///...
var
Form1: TForm1;
pushed:Boolean;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
pushed:=false;
repeat
Application.HandleMessage;
until pushed;
ShowMessage('Done!');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
pushed:=True;
end;
//...[/no]
Автор: Man_Without_Face
Дата сообщения: 20.04.2010 07:58
Frodo_Torbins
В том то и дело что ехе - Delphi 5 а Dll - Delphi 2009. Вопрос в том почему вторая форма не загружается, может как то не так создаю? (первая невидимая, а вторую нужно показать для внесения значений).

Добавлено:
Спасибо, вроде сделал...
Автор: Who_is_you
Дата сообщения: 20.04.2010 10:06
Читаю с Сом порта функцией ReadFile по приходу символа (ставлю маску EV_RXFLAG).
Открываю порт, жду символ, читаю.
Нужно принять 10 таких строк.

Если запускаю программу *.exe, то все четко работает.
Если не выходя из программы закрываю порт, а потом открываю заново и читаю, то первую строку не получаю.
Получается вошел в программу: первый раз прочитал 10 строк, а второй, третий и т.д. - 9строк.

Как с этим бороться?
Автор: Man_Without_Face
Дата сообщения: 20.04.2010 11:00
Может кто подскажет почему в Dll при рантайме не поддерживаются скины (DevExpress v48), в дезайн выставляю и все отлично меняется? В exe и там и там нормально.
Автор: Frodo_Torbins
Дата сообщения: 20.04.2010 11:55
Man_Without_Face
Нормальная работа VCL в dll без использования пакетов не гарантируется, об этом написано в справке. Обычно это приводит к возникновению самых странных и непредсказуемых глюков. Собственно поэтому вас тут так агитировали использовать пакеты. Но раз у вас разные версии делфи, и это не возможно, то остается только минимизировать использование VCL в библиотеке.
Автор: apnss
Дата сообщения: 20.04.2010 14:10
Frodo_Torbins

о каких конкретно глюках идет речь, интересно?

у меня, к примеру, описан класс формы - родитель всех МДИчайлдов проекта. часть чайлдов реализована в виде модулей приложения, а часть в виде ДЛЛ дабы не прикомпиливать к основной ЕХЕ-хе фастреорт и иеже с ним. Пришлось пострадать с реализацией калбэков для обновления менюх главной формы, но сейчас - все нормально крутиться


Добавлено:

а, забыл добавить

часть методов родительской формы представляет собой абстрактные методы для поддержки универсальности всех наследников с точки зрения главной формы приложения.
Автор: AlexIntegral
Дата сообщения: 20.04.2010 21:34
для Frodo_Torbins


Цитата:
AlexIntegral
Либо Sleep(n{секунд}*1000), либо так если приложение должно реагировать на действия пользователя во время паузы. Последний способ требует акуратной блокировки интерфейса, чтобы пользователь не нажал чего лишнего.


Можно ли делать так?

for i:=2 to n do
begin
Application.ProcessMessages;
if RadioButton1.Checked=true then Application.HandleMessage;
....
end;

Цикл приостанавливается, но при движении курсора над формой цикл медленно работает (зависит от того как быстро двигать курсором), можно ли этого избежать?
Автор: Frodo_Torbins
Дата сообщения: 20.04.2010 21:57
apnss
Глюки были самые разные, от странного поведения контролов до неожиданных AV.

AlexIntegral
Выделю ка я свой код в отдельную процедуру, чтобы было понятнее:
Код: [no]Procedure Wait;
begin
repeat
Application.HandleMessage;
until RadioButton1.Checked=true;
//ждем пока юзер не нажмет радиобуттон
//возможно нужно "<>", вам виднее
end;

for i:=2 to n do
begin
//тут что то делали, и решили передохнуть
Wait;
//...
end;[/no]
Автор: apnss
Дата сообщения: 20.04.2010 21:59
Frodo_Torbins
"Левые" компоненты юзались? в одном проекте было что-то похожее, но после того как искоренили TMS все заработало как часы...
Автор: Frodo_Torbins
Дата сообщения: 20.04.2010 22:18
apnss
В "левых" компонентах вся суть и была. В конце-концов решено было просто обьединить код библиотеки и приложения. После этого все глюки чудесным образом исчезли.
Автор: AlexIntegral
Дата сообщения: 20.04.2010 22:29
Frodo_Torbins

Большое спасибо, я понял
Автор: SIgor33
Дата сообщения: 21.04.2010 08:46
Есть поисковая машина Интегра http://www.solarix.ru/ в ней обертка для delphi кто нибудь ее использовал а то я делаю так
var
new: PInteger;
begin
new:=SearchEngineApi.sol_CreateSearchEngine();
SearchEngineApi.sol_LoadDictionaryA( new, PChar('E:\dictionary.xml'));
SearchEngineApi.sol_DeleteSearchEngine(new);

end;
лезет ошибка при загрузке словаря хотя в их файле вызов описан так


// Load the dictionary (morphology and syntax analyzer + thesaurus)
// Return: 2 - already loaded, 1 - ok, 0 - error has occured.
function sol_LoadDictionaryA( hEngine: PInteger; Filename: PAnsiChar ): integer; stdcall; external 'faind.win32.dll' name 'sol_LoadDictionaryA';


Автор: Odysseos
Дата сообщения: 21.04.2010 10:18
SIgor33

Какая версия Delphi? Если 2009+ - то вызов SearchEngineApi.sol_LoadDictionaryA( new, PChar('E:\dictionary.xml')); поправьте вот так - SearchEngineApi.sol_LoadDictionaryA( new, PAnsiChar('E:\dictionary.xml'));
Автор: SIgor33
Дата сообщения: 21.04.2010 10:20
Odysseos
Delphi 7
Автор: Odysseos
Дата сообщения: 21.04.2010 10:34
SIgor33

А ошибка-то хоть какая?

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

Предыдущая тема: Clipper 5


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.