Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
Задача написать DLL обертку для работы с датасетом (используется TADOQuery).
Есть внешнее приложение в котором нужно вернуть последовательно строки датасета, для последующей обработки.
Работа с датасетом идет через DLL
Как сделать обертку для метода ADOQuery.Next ?

Т.е. из внешнего приложения код будет такого вида:
// передача и выполнение запроса в 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);
23 дек 18, 14:21    [21771405]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3825
Петр,

Пусть указатель на объект TDataset и будет handle.
Заменить sql_query.EOF на функцию sql_query_EOF, sql_query.Next на функцию sql_query.Next, и всё - можно все остальное так и оставить.
А еще можно - объединить их в одну функцию sql_query_fetch.
23 дек 18, 17:12    [21771479]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
да но как мне правильно объявить этот указатель в DLL, чтобы он был виден во внешнем приложении?
23 дек 18, 23:20    [21771642]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Фэйтл Эра
Member

Откуда:
Сообщений: 630
Петр,

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

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

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):
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.
24 дек 18, 00:04    [21771658]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3825
Петр
да но как мне правильно объявить этот указатель в DLL, чтобы он был виден во внешнем приложении?
Никак не объявить. Его будет возвращать ф-ция set_sql_query.
24 дек 18, 03:35    [21771700]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
YuRock
Петр
да но как мне правильно объявить этот указатель в DLL, чтобы он был виден во внешнем приложении?
Никак не объявить. Его будет возвращать ф-ция set_sql_query.


что-то не работает:
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;
24 дек 18, 14:47    [21772154]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
Фэйтл Эра
Петр,

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

т.е. вы возвращаете сразу массив?
не работал никогда в "интерфейсом", в данном случае почему именно он используется?
24 дек 18, 14:52    [21772160]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Фэйтл Эра
Member

Откуда:
Сообщений: 630
Петр,

тебе надо разобраться, что такое интерфейс.
24 дек 18, 15:25    [21772208]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3825
Петр
что-то не работает
т.к. очень много ошибок.
1. Addr не нужен, просто приводи к типу. А то получается указатель на указатель, который ты потом не разадресовываешь.
2. Что за ADOConnection, кто его создает - неизвестно.
3. Твой ErrMessage - это ад какой-то. Ты туда мертвый указатель посылаешь зачастую.
24 дек 18, 15:38    [21772222]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3825
Петр,

Зачем это все надо? Для общего развития?
Удобно так не будет. Пусть dll лучше возвращает результат, а не буффер из базы данных.
24 дек 18, 15:41    [21772226]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
YuRock
Петр
что-то не работает
т.к. очень много ошибок.
1. Addr не нужен, просто приводи к типу. А то получается указатель на указатель, который ты потом не разадресовываешь.
2. Что за ADOConnection, кто его создает - неизвестно.
3. Твой ErrMessage - это ад какой-то. Ты туда мертвый указатель посылаешь зачастую.


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

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

зачем надо:

надо чтобы из другой программы (язык MQL4) получить последовательность записей запроса Query (select * from table)
24 дек 18, 16:17    [21772273]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
могу привести весь код если надо для теста
24 дек 18, 16:23    [21772277]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
ziv-2014
Member

Откуда:
Сообщений: 235
Петр,
1. Для начала передаешь widestring, а не PWidechar. Pwidechar - ссылкается на string, который может в любое время уничтожиться.
2. Result := Pointer(ADOQuery);
3. Помни про общий менеджер памяти.
4. Сделай все на интерфейсах+widestring, так жить проще. Интерфейсы - это классы, только лучше :)
24 дек 18, 16:25    [21772279]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
ziv-2014
Member

Откуда:
Сообщений: 235
Петр,
1. Ничего не делай в секциях initialization и finalization - ибо грех это.
2. Multithreaded = true - это тоже важно.
3. CoInitializate - надо наверное тоже сделать, и обратную процедуру не забыть.
В чем ошибка-то?
24 дек 18, 16:28    [21772281]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
ziv-2014
Member

Откуда:
Сообщений: 235
Петр,
Для начала научись передавать просто текст из mql4 в приложение. А потом займись уже Ado.
24 дек 18, 16:36    [21772284]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
итак вроде что-то вырисовывается:
Код в принципе заработал. Первый затык был
result := TADOQuery(aADOQuery).Fields[ColIndex].AsInteger;

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


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

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

главный вопрос именно в правильном объявлении 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 := 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;
24 дек 18, 17:41    [21772328]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Фэйтл Эра
Member

Откуда:
Сообщений: 630
Петр,

передача объекта по ссылке из dll чрезвычайно опасна. Даже изменение опций того же самого компилятора может повлечь трудноуловимые глюки.
24 дек 18, 17:49    [21772334]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
Фэйтл Эра
Петр,

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


возможно, как тогда решить задачу? Возвращением массива? Хотя тут я тоже не уверен, что получиться его правильно вернуть...
24 дек 18, 17:57    [21772338]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3825
Петр
возможно, как тогда решить задачу?
Мы откуда знаем. Ты ж условие задачи не говоришь.
24 дек 18, 18:05    [21772341]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Петр
Member

Откуда: Москва
Сообщений: 741
YuRock
Петр
возможно, как тогда решить задачу?
Мы откуда знаем. Ты ж условие задачи не говоришь.


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

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

надо чтобы из другой программы (язык MQL4) получить последовательность записей запроса Query (select * from table)
24 дек 18, 18:10    [21772348]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3825
Петр
надо чтобы из другой программы (язык MQL4)
В нем точно можно dll подключать?
Если да - то что-то вроде 1-го твоего поста. Но только надо изучить, как работать с памятью и все остальное.
Как передавать во внешнюю прогу строки и прочее. Буфферы для этого должны быть выделены там,
а значит - сначала надо их подготовить, а лишь затем - фетчить записи.
24 дек 18, 21:19    [21772480]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Фэйтл Эра
Member

Откуда:
Сообщений: 630
Петр
надо чтобы из другой программы (язык MQL4) получить последовательность записей запроса Query (select * from table)

Что ж ты сразу не сказал про мкл4.

Фиг тебе, а не интерфейсы.
И, естественно, никаких тебе объектов из dll.
Используй какую-нибудь json или xml или csv для возврата структур. Проще всего возвращать все записи сразу. Ибо иначе тебе придется в длл готовить и хранить контекст запроса. Ничего сложного, просто кодить больше.
24 дек 18, 21:38    [21772488]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Gator
Member

Откуда: Москва
Сообщений: 14084
Фэйтл Эра
И, естественно, никаких тебе объектов из dll.
Стесняюсь спросить, тебе религия мешает?
24 дек 18, 21:42    [21772490]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Фэйтл Эра
Member

Откуда:
Сообщений: 630
Gator
Фэйтл Эра
И, естественно, никаких тебе объектов из dll.
Стесняюсь спросить, тебе религия мешает?

Ну расскажи скорее, как объекты Delphi в MQL4 использовать.
24 дек 18, 21:49    [21772495]     Ответить | Цитировать Сообщить модератору
 Re: обращение к DataSet через dll  [new]
Gator
Member

Откуда: Москва
Сообщений: 14084
Фэйтл Эра,
Алрес, он и в Африке - адрес. На что он указывает и когда - тебе знать надо (область видимости). Адреc обеспечиваешь ты, как и структуру по этому адресу. Главное, вовремя данные обеспечить и память освободить
24 дек 18, 21:59    [21772505]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Delphi Ответить