![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
В DLL у меня происходят вычисления и в основную программу передается массив записей.
Но, почему то после успешной отработки DLL я не могу работать с возвращенными данными Собственно код... Код:
Общий класс основной программы и DLL
...
type
TKoef = Record
name: PChar;
abbr: PChar;
val_bgn: real;
val_end: real;
delta: real;
criterion: boolean;
cr_min: real;
cr_max: real;
dev_bgn: boolean;
dev_end: boolean;
dev_bgn_val: real;
dev_end_val: real;
info: PChar;
valid: boolean;
end;
Основная программа
...
type
TArr = array of TKoef;
TPArr = ^TArr;
...
procedure TfMain.mModuleCalcClick(Sender: TObject);
var
Arr: TArr;
PArr: TPArr;
begin
try
try
hDLL := LoadLibrary(PAnsiChar(FN));
@GetModuleData := nil;
if hDLL >= 32 then begin
@GetModuleData := GetProcAddress(hDLL,'GetModuleData');
if (@GetModuleData<>nil) then begin
SetLength(Arr,5);
PArr := Addr(Arr);
if GetModuleData(ORG, PArr) then begin
---> вот здесь я пытаюсь работать с Arr, но вылетают ошибки
end;
end;
end;
finally
@GetModuleData := nil;
FreeLibrary(hDLL);
end;
except
end;
end;
...
DLL
...
const
KOEF_CLOUNT = 5;
type
TArr = array[1..KOEF_CLOUNT] of TKoef;
TPArr = ^TArr;
...
function GetModuleData(dllORG: TOrganization; aPArr:TPArr): Boolean; stdcall;
begin
with aPArr^[1] do begin
...
end;
...
with aPArr^[5] do begin
...
end;
end;
...
|
|
#2
|
|||
|
|||
|
Ну так в основной программе
Код:
array of TKoeff Код:
array [1..of KOEF_CLOUNT] TKoeff В основной программе надо Код:
type TArr = array of TKoef; TPArr = ^TKoef; // <<==-- Вот TGetModuleData = function (dllORG: TOrganization; aPArr:TPArr): Boolean; stdcall; ... PArr := @(Arr[0]); //<<==-- Вот if GetModuleData(ORG, PArr) ... |
|
#3
|
||||
|
||||
|
И еще в процедурах, которые возвращают данные в параметрах, обьявляй эти параметры после var.
Код:
function GetModuleData(dllORG: TOrganization;var aPArr:TPArr): Boolean; stdcall; |
|
#4
|
|||
|
|||
|
Всем спасибо.
Сделал так: передача массива не через указатель на массив, а собственно передача динамического массива. И в программе и в ДЛЛ стал использовать единый тип (динамический массив). Все работает. |
|
#5
|
|||
|
|||
|
Цитата:
А вот это вредный совет. |
|
#6
|
|||
|
|||
|
Цитата:
А для такого способа не забывать внимательно читать комментарий, который Delphi пишет в заготовке проекта DLL. |
|
#7
|
|||
|
|||
|
Не совсем понял о чем речь...
|
|
#8
|
||||
|
||||
|
Цитата:
. Посоветовал то, что сам использую. Конечно есть out, но это не выход. (в смысле, из положения )Насчет поста о комментарии в DLL - я тоже ничего не понял. Там, кажись, написано о строках, а не динамических массивах. ИМХО все из-за совместимости dll для разных языков программирования. И ТС использует PChar, String нигде нет. |
|
#9
|
|||
|
|||
|
В алгоритме, который привёл автор топика, в DLL передаётся указатель на уже выделенную память, в DLL она только заполняется. Поэтому лишний var тут не нужен. Var может понадобится в случае, когда передаётся структура и в DLL она будет изменена. Посмотрите модуль windows.pas. Во многих случаях, когда в API функции требуется указатель на переменную или структуру, в паскале используется синтаксис в var. А когда нужен массив - используются указатели.
По поводу комментария - механизм работы со строками и динамическими массивами один и тот же. |
|
#10
|
|||
|
|||
|
Спасибо за информацию.
Сейчас вычисления в DLL проходят нормально и результаты я использую в основной программе, но при закрытии программы вылетает ошибка чтения памяти. Может надо какой ресурс очистить? Код ниже Это общий класс DLL и основной программы Код:
unit uExchange;
interface
uses SysUtils;
const
F1_COUNT = 67;
F2_COUNT = 21;
F5_COUNT = 10;
type
TKoef = Record
name: String;
abbr: String;
val_bgn: Currency;
val_end: Currency;
delta: Currency;
criterion: boolean;
cr_type: integer;
cr_min: Currency;
cr_max: Currency;
dev_bgn: boolean;
dev_end: boolean;
dev_bgn_val: Currency;
dev_end_val: Currency;
info: String;
valid: boolean;
end;
TMKoef = array of TKoef;
TModule = Record
id: integer;
koef_count: integer;
mKoef: TMKoef;
isCalc: Boolean;
end;
TOrganization = record
FileName: String;
Name: String;
Address: String;
Ruk: String;
RukPhone: String;
Buh: String;
BuhPhone: String;
INN: String;
KPP: String;
EMail: String;
BankName: String;
BankBIK: String;
BankKS: String;
OKPO: String;
OKVED: String;
Information: String;
f1: array[1..4,1..F1_COUNT] of String;
f2: array[1..4,1..F2_COUNT] of String;
f5: array[1..4,1..F5_COUNT] of String;
modules: array of TModule;
end;
implementation
...
end.Это DLL Код:
library module1; uses uExchange, SysUtils; function GetModuleData(var O: TOrganization; module_number:integer): Boolean; stdcall; begin with O.modules[module_number].mKoef[0] do begin ... end; with O.modules[module_number].mKoef[1] do begin ... end; Result := True; end; exports GetModuleData; begin end. И код программы Код:
public
ORG: TOrganization;
...
GetModuleData: function(var O: TOrganization; module_number: integer): Boolean; stdcall;
...
procedure TfMain.mModuleCalcClick(Sender: TObject);
begin
try
try
hDLL := LoadLibrary(PAnsiChar(FN));
@GetModuleData := nil;
if hDLL >= 32 then begin
@GetModuleData := GetProcAddress(hDLL,'GetModuleData');
if (@GetModuleData<>nil) then begin
GetModuleData(ORG, 0) then begin
end;
end;
finally
@GetModuleData := nil;
FreeLibrary(hDLL);
end;
except
end;
end;
... |
| Этот пользователь сказал Спасибо Сергей77 за это полезное сообщение: | ||
OTVET (22.01.2013)
| ||
|
#11
|
||||
|
||||
|
to icWasya
Цитата:
Ну, если так, то сделай следующее: Обьяви динамический массив размером 5 и строку длиной 5 символов, затем попробуй обратится к массив[5] элементу и строка[5] элементу, а также массив[0] элементу и строка[0] элементу - скажи что получилось. И как dll должна реагировать на 0 элемент строки. Как я уже писал, в разных языках программирования (отчасти Delphi и C) строки отличаются друг от друга, и в С строка оканчивается на NULL(для признака последнего символа), в Delphi же в 0 индексе содержится информация о длне строки. Так что эта заметка к динамическим массивам отношения не имеет. to Сергей77 А если запускать не из среды программирования, вылеты тоже наблюдаются? |
|
#12
|
|||
|
|||
|
Да. При завершении работы выскакивает, что программа некорректные действия и та же ошибка памяти.
|
|
#13
|
|||
|
|||
|
>но при закрытии программы вылетает ошибка чтения памяти.
Ну вот как раз на такой случай и нужно прочитать комментарий в заготовке DLL. На этот раз у Вас в передаваемой структуре находятся строки, при работе с которыми возможно перевыделение памяти. |
| Этот пользователь сказал Спасибо icWasya за это полезное сообщение: | ||
Сергей77 (03.10.2012)
| ||
|
#14
|
||||
|
||||
|
Ну да, как уже раньше писалось - у тебя в классах используются String, а их для отправки в DLL использовать не рекомендуется. Поменяй String на PChar или ShortString, или, как пишет в комментарии при создании DLL из визарда, пропиши ShareMem первим в разделе Uses, но тогда твоя прога будет зависимая от BORLANDMM.DLL. Выбирай меньшее из двух зол
![]() |
|
#15
|
|||
|
|||
|
Спасибы.
Ваши ответы мне помогли. |
![]() |
|
| Опции темы | Поиск в этой теме |
| Опции просмотра | |
|
|