Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / обращение к DataSet через dll / 25 сообщений из 37, страница 1 из 2
23.12.2018, 14:21
    #39751861
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Задача написать DLL обертку для работы с датасетом (используется TADOQuery).
Есть внешнее приложение в котором нужно вернуть последовательно строки датасета, для последующей обработки.
Работа с датасетом идет через DLL
Как сделать обертку для метода ADOQuery.Next ?

Т.е. из внешнего приложения код будет такого вида:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
// передача и выполнение запроса в DLL и возвращение хендла
handle := <set_sql_query('select * from table', var <кол столбцов>)> 

while (not <sql_query.EOF(handle)>) // пока есть необработанная строка в датасете
begin
  // получаем значение столбцов текущей строки 
  volum_column1 := get_volum_column1(handle, 1);
  volum_column2 := get_volum_column2(handle, 2);
  volum_column3 := get_volum_column3(handle, 3);
  // переход на следующую строку
  <sql_query.Next(handle)>
end
// освобождение хендля
free_sql_query (handle);
...
Рейтинг: 0 / 0
23.12.2018, 17:12
    #39751902
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр,

Пусть указатель на объект TDataset и будет handle.
Заменить sql_query.EOF на функцию sql_query_EOF, sql_query.Next на функцию sql_query.Next, и всё - можно все остальное так и оставить.
А еще можно - объединить их в одну функцию sql_query_fetch.
...
Рейтинг: 0 / 0
23.12.2018, 23:20
    #39751965
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
да но как мне правильно объявить этот указатель в DLL, чтобы он был виден во внешнем приложении?
...
Рейтинг: 0 / 0
24.12.2018, 00:04
    #39751975
Фэйтл Эра
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр,

импортируй из dll интерфейс. У меня, например, такой интерфейс реализует метод GetNewQuey:
Код: pascal
1.
2.
    function GetNewQuery(aTransactionKind: TCommonTransactionKind = trcRead):
      ICommonQuery;


Где ICommonQuery выглядит (примерно) так:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
ICommonQuery = interface(IUnknown)


    procedure Close;
    procedure ExecQuery;
    procedure ExecProc;
    function FieldByName(const AFieldName: string): ICommonField;
    function FN(const AFieldName: string): ICommonField;
    function ParamByName(const AParamName: string): ICommonField;
    function FieldCount: Integer;
    function GetFields(Index: Integer): ICommonField;
    function GetParameters(Index: Integer): ICommonField;
    function GetSQLText: string;
    function EOF: Boolean;
    function FieldExist(const aFieldName: string; var aIdx: Integer): Boolean;
    procedure Next;
    procedure Prepare;
    function RecordCount: Integer;
    procedure SetSQLText(const Value: string);
    procedure SQLAdd(aItem: string);
    procedure SQLClear;
    function GetTransaction: ICommonTransaction;
    procedure SetTransaction(const Value: ICommonTransaction);
    property Fields[Index: Integer]: ICommonField read GetFields;
    property Parameters[Index: Integer]: ICommonField read GetParameters;
    property SQLText: string read GetSQLText write SetSQLText;
    property Transaction: ICommonTransaction read GetTransaction write
      SetTransaction;
  end;



Реализация - в соответствии с внутренними особенностями используемых компонентов.

Использование (например, заполнение массива aReports):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
procedure GetListReports(var aReports: TReports);
var
  fqGet: ICommonQuery;
begin
  SetLength(aReports, 0);
  fqGet := ConnectDataModule.GetNewQuery();
  fqGet.SQLAdd('select r.Report_id, r.Report_Type, r.Name ');
  fqGet.SQLAdd(' from Reports r order by r.Name');
  fqGet.ExecQuery;
  while not fqGet.Eof do
  begin
    SetLength(aReports, length(aReports) + 1);
    aReports[High(aReports)].id := fqGet.FieldByName('Report_id').AsInteger;
    aReports[High(aReports)].RepType := fqGet.FieldByName('Report_Type').AsString;
    aReports[High(aReports)].RepName := fqGet.FieldByName('Name').AsString;
    fqGet.Next
  end;
end;



Здесь ConnectDataModule - "корневой" интерфейс, импортированный из dll.
...
Рейтинг: 0 / 0
24.12.2018, 03:35
    #39752003
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петрда но как мне правильно объявить этот указатель в DLL, чтобы он был виден во внешнем приложении?Никак не объявить. Его будет возвращать ф-ция set_sql_query.
...
Рейтинг: 0 / 0
24.12.2018, 14:47
    #39752305
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
YuRockПетрда но как мне правильно объявить этот указатель в DLL, чтобы он был виден во внешнем приложении?Никак не объявить. Его будет возвращать ф-ция set_sql_query.

что-то не работает:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
var
  ADOQuery: TADOQuery;
***
function open_query(SQL: PWideChar; var ErrMessage: PWideChar): Pointer stdcall;
begin
 try
  ADOQuery := TADOQuery.Create(nil);

  if not ADOConnection.Connected then
   begin
     ErrMessage := 'Connection not exists (open_query)';
     exit;
   end;

  ADOQuery.Connection := ADOConnection;
  ADOQuery.SQL.Text := SQL;

  ADOQuery.Open;
  ADOQuery.First;
  //result := Integer(Addr(ADOQuery));
  result := Addr(ADOQuery);
 except
   on e: Exception do ErrMessage := PWideChar(E.Message);
 end;
end;

function get_value_int(aADOQuery: Pointer; ColIndex: integer; var ErrMessage: PWideChar):integer stdcall;
begin
 result := -1;
 try
  if not ADOConnection.Connected then
   begin
     ErrMessage := 'Connection not exists (get_value_int)';
     exit;
   end;

  if not TADOQuery(aADOQuery).Active then
   begin
     ErrMessage := 'Query not open (get_value_int)';
     exit;
   end;

  result := TADOQuery(aADOQuery).Fields[ColIndex].AsInteger;

  if not TADOQuery(aADOQuery).Eof then TADOQuery(aADOQuery).Next;
 except
   on e: Exception do ErrMessage := PWideChar(E.Message);
 end;
end;
...
Рейтинг: 0 / 0
24.12.2018, 14:52
    #39752311
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Фэйтл ЭраПетр,

импортируй из dll интерфейс. У меня, например, такой интерфейс реализует метод GetNewQuey:
Код: pascal
1.
2.
    function GetNewQuery(aTransactionKind: TCommonTransactionKind = trcRead):
      ICommonQuery;


т.е. вы возвращаете сразу массив?
не работал никогда в "интерфейсом", в данном случае почему именно он используется?
...
Рейтинг: 0 / 0
24.12.2018, 15:25
    #39752338
Фэйтл Эра
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр,

тебе надо разобраться, что такое интерфейс.
...
Рейтинг: 0 / 0
24.12.2018, 15:38
    #39752349
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петрчто-то не работаетт.к. очень много ошибок.
1. Addr не нужен, просто приводи к типу. А то получается указатель на указатель, который ты потом не разадресовываешь.
2. Что за ADOConnection, кто его создает - неизвестно.
3. Твой ErrMessage - это ад какой-то. Ты туда мертвый указатель посылаешь зачастую.
...
Рейтинг: 0 / 0
24.12.2018, 15:41
    #39752353
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр,

Зачем это все надо? Для общего развития?
Удобно так не будет. Пусть dll лучше возвращает результат, а не буффер из базы данных.
...
Рейтинг: 0 / 0
24.12.2018, 16:17
    #39752383
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
YuRockПетрчто-то не работаетт.к. очень много ошибок.
1. Addr не нужен, просто приводи к типу. А то получается указатель на указатель, который ты потом не разадресовываешь.
2. Что за ADOConnection, кто его создает - неизвестно.
3. Твой ErrMessage - это ад какой-то. Ты туда мертвый указатель посылаешь зачастую.

ошибок не дает, но значение поля не возвращает.

1. подскажите как правильно, не селен в указателях
2. не весь код прислал. ADOConnection - устанавливает коннект с БД
3. ErrMessage - это не важно

зачем надо:

надо чтобы из другой программы (язык MQL4) получить последовательность записей запроса Query (select * from table)
...
Рейтинг: 0 / 0
24.12.2018, 16:23
    #39752384
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
могу привести весь код если надо для теста
...
Рейтинг: 0 / 0
24.12.2018, 16:25
    #39752385
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр,
1. Для начала передаешь widestring, а не PWidechar. Pwidechar - ссылкается на string, который может в любое время уничтожиться.
2. Result := Pointer(ADOQuery);
3. Помни про общий менеджер памяти.
4. Сделай все на интерфейсах+widestring, так жить проще. Интерфейсы - это классы, только лучше :)
...
Рейтинг: 0 / 0
24.12.2018, 16:28
    #39752387
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр,
1. Ничего не делай в секциях initialization и finalization - ибо грех это.
2. Multithreaded = true - это тоже важно.
3. CoInitializate - надо наверное тоже сделать, и обратную процедуру не забыть.
В чем ошибка-то?
...
Рейтинг: 0 / 0
24.12.2018, 16:36
    #39752389
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр,
Для начала научись передавать просто текст из mql4 в приложение. А потом займись уже Ado.
...
Рейтинг: 0 / 0
24.12.2018, 17:41
    #39752405
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
итак вроде что-то вырисовывается:
Код в принципе заработал. Первый затык был
Код: pascal
1.
result := TADOQuery(aADOQuery).Fields[ColIndex].AsInteger;


по индексу значение не выдавалось, заменил на
Код: pascal
1.
result := TADOQuery(aADOQuery).FieldByName(FieldName).AsInteger;



тип PWideChar - был выбран не случайно с widestring не работает.

значения integer DLL возвращает правильно, символьные возвращает в виде: '??' - похоже в кодировке проблема

главный вопрос именно в правильном объявлении TADOQuery - где и как объявлять?

на данный момент:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
function open_query(SQL: PWideChar; var ErrMessage: PWideChar): Pointer stdcall;
begin
 try
  ADOQuery := TADOQuery.Create(nil);

  if not ADOConnection.Connected then
   begin
     ErrMessage := 'Connection not exists (open_query)';
     exit;
   end;

  ADOQuery.Connection := ADOConnection;
  ADOQuery.SQL.Text := SQL;

  ADOQuery.Open;
  ADOQuery.First;
  //result := Integer(Addr(ADOQuery));
  result := Pointer(ADOQuery);
 except
   on e: Exception do ErrMessage := PWideChar(E.Message);
 end;
end;

function get_value_int(aADOQuery: Pointer; FieldName: PWideChar; var ErrMessage: PWideChar):integer stdcall;
begin
 result := -1;
 ErrMessage := 'OK';
 try
  if not ADOConnection.Connected then
   begin
     ErrMessage := 'Connection not exists (get_value_int)';
     exit;
   end;

  if not TADOQuery(aADOQuery).Active then
   begin
     ErrMessage := 'Query not open (get_value_int)';
     exit;
   end;

  result := TADOQuery(aADOQuery).FieldByName(FieldName).AsInteger;

  if not TADOQuery(aADOQuery).Eof then TADOQuery(aADOQuery).Next;
 except
   on e: Exception do ErrMessage := PWideChar(E.Message);
 end;
end;
...
Рейтинг: 0 / 0
24.12.2018, 17:49
    #39752407
Фэйтл Эра
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр,

передача объекта по ссылке из dll чрезвычайно опасна. Даже изменение опций того же самого компилятора может повлечь трудноуловимые глюки.
...
Рейтинг: 0 / 0
24.12.2018, 17:57
    #39752410
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Фэйтл ЭраПетр,

передача объекта по ссылке из dll чрезвычайно опасна. Даже изменение опций того же самого компилятора может повлечь трудноуловимые глюки.

возможно, как тогда решить задачу? Возвращением массива? Хотя тут я тоже не уверен, что получиться его правильно вернуть...
...
Рейтинг: 0 / 0
24.12.2018, 18:05
    #39752413
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петрвозможно, как тогда решить задачу?Мы откуда знаем. Ты ж условие задачи не говоришь.
...
Рейтинг: 0 / 0
24.12.2018, 18:10
    #39752415
Петр
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
YuRockПетрвозможно, как тогда решить задачу?Мы откуда знаем. Ты ж условие задачи не говоришь.

дважды сказал:
2-я строка первого поста:
Есть внешнее приложение в котором нужно вернуть последовательно строки датасета, для последующей обработки.

и ниже по тексту:
зачем надо:

надо чтобы из другой программы (язык MQL4) получить последовательность записей запроса Query (select * from table)
...
Рейтинг: 0 / 0
24.12.2018, 21:19
    #39752510
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр надо чтобы из другой программы (язык MQL4) В нем точно можно dll подключать?
Если да - то что-то вроде 1-го твоего поста. Но только надо изучить, как работать с памятью и все остальное.
Как передавать во внешнюю прогу строки и прочее. Буфферы для этого должны быть выделены там,
а значит - сначала надо их подготовить, а лишь затем - фетчить записи.
...
Рейтинг: 0 / 0
24.12.2018, 21:38
    #39752518
Фэйтл Эра
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Петр надо чтобы из другой программы (язык MQL4) получить последовательность записей запроса Query (select * from table)
Что ж ты сразу не сказал про мкл4.

Фиг тебе, а не интерфейсы.
И, естественно, никаких тебе объектов из dll.
Используй какую-нибудь json или xml или csv для возврата структур. Проще всего возвращать все записи сразу. Ибо иначе тебе придется в длл готовить и хранить контекст запроса. Ничего сложного, просто кодить больше.
...
Рейтинг: 0 / 0
24.12.2018, 21:42
    #39752520
Gator
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Фэйтл ЭраИ, естественно, никаких тебе объектов из dll.Стесняюсь спросить, тебе религия мешает?
...
Рейтинг: 0 / 0
24.12.2018, 21:49
    #39752524
Фэйтл Эра
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
GatorФэйтл ЭраИ, естественно, никаких тебе объектов из dll.Стесняюсь спросить, тебе религия мешает?
Ну расскажи скорее, как объекты Delphi в MQL4 использовать.
...
Рейтинг: 0 / 0
24.12.2018, 21:59
    #39752531
Gator
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
обращение к DataSet через dll
Фэйтл Эра,
Алрес, он и в Африке - адрес. На что он указывает и когда - тебе знать надо (область видимости). Адреc обеспечиваешь ты, как и структуру по этому адресу. Главное, вовремя данные обеспечить и память освободить
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / обращение к DataSet через dll / 25 сообщений из 37, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]