Лена |
Отправлено: 22.11.2006, 10:38 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Впервые в жизни надо написать DLL.
В DLL должна быть функция, которая принимал бы указатель на строку (char *). Далее эта функция просматривала бы определенную колонку в ClientDataset и если строка есть, то возвращала бы ее, а если нет, то возвращала бы NULL. Думаю что-то похожее уже должно существовать в качестве примера. Подскажите ссылку.
P.S.
Смутно представляю как в функции DLL получить доступ к ClientDataset приложения.
А если задача усложниться и надо будет получить доступ к полю которое храниться в базе на удаленном сервере, то тогда вообще не понятно как такое реализовать.
Отредактировано Лена — 22.11.2006, 11:05 |
|
exp |
Отправлено: 22.11.2006, 11:57 |
|
Мастер участка
Группа: Участник
Сообщений: 304
|
примерчик в аттаче.
|
|
olegenty |
Отправлено: 22.11.2006, 12:27 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
Лиха беда начало. Я уже скоро забуду, что такое EXE: запускающий модуль практически не меняется около года, а весь функционал давно в DLL.
|
|
Лена |
Отправлено: 22.11.2006, 12:49 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Создала DLL и h файл к ней, теперь добавила модуль данных для связи с базой и добавила в него h файл dll.
Правильной дорогой иду? |
|
Лена |
Отправлено: 22.11.2006, 13:12 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
В DLL у меня пока так:
CODE |
#pragma argsused
#include "UFind.h" //h файл DLL
#include "UDataModule.h" //Дата модуль
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
char * FindRecord(char *s)
{
//тут искать запись
return s;
}
|
В UFind.h так:
CODE |
#ifndef _UFIND_H
#define _UFIND_H
#ifdef __DLL__
#define DLL_EI __declspec(dllexport)
#else
#define DLL_EI __declspec(dllimport)
#endif
extern "C" char * DLL_EI FindRecord(char *s);
#endif
|
Правильно? |
|
AVC |
Отправлено: 22.11.2006, 13:59 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Датамодуль в отдельный пакет(dll) и использовать его в exe и прочих пакетах. В него включаются сессия и базовые функции для работы с базой. Наборы данных создает каждый пакет у себя по мере надобности. |
|
Лена |
Отправлено: 22.11.2006, 17:43 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Код в DLL такой:
CODE |
#pragma argsused
#include "UFind.h" //h файл DLL
#include "UDataModule.h" //Дата модуль
#include <stdio.h>
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
char buf[1024];
char * FindRecord(char *param)
{
int Test = 0; //сразу исключение
DataModule1->ADOQuery1->Active = false;
DataModule1->ADOQuery1->SQL->Clear();
sprintf(buf, "select code from key where code = \"%s\"", param);
DataModule1->ADOQuery1->SQL->Text = String(buf);
DataModule1->ADOQuery1->Active = true;
char *res = NULL;
if (DataModule1->ADOQuery1->RecordCount == 0)
; // ничего не делать вообще
else {
res = new char[DataModule1->ADOQuery1->FieldByName("code")->AsString.Length() + 1];
strcpy(res, DataModule1->ADOQuery1->FieldByName("code")->AsString.c_str());
}
DataModule1->ADOQuery1->Active = false;
return res;
}
|
Создала тестовое приложение. Добавила в него lib файл. Код тестового приложения:
CODE |
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "UFind.h" //DLL
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit1->Text = FindRecord(Edit1->Text.c_str());
}
//---------------------------------------------------------------------------
|
При нажатии на кнопку получаю исключение на первой же строке FindRecord
Присоединить изображение
|
|
olegenty |
Отправлено: 22.11.2006, 17:57 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
в отладчик и разбираться.
|
|
Лена |
Отправлено: 22.11.2006, 18:21 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Мне кажется, что Дата Модуль просто не создается, хоть он и есть в DLL. |
|
olegenty |
Отправлено: 22.11.2006, 18:24 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
автоматически в DLL НИЧЕГО не создаётся. всё надо делать руками. и создавать, и удалять. вариантов комбинаций много, но лично я предпочитаю, чтобы за выдеоение и освобождение памяти отвечала DLL, а управлял этим процессом EXE.
|
|
Лена |
Отправлено: 22.11.2006, 18:28 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Где создовать в коде Дата Модуль? А компонеты которые лежат на Дата Модуле типа ADOquery, тоже создовать надо? |
|
olegenty |
Отправлено: 22.11.2006, 18:31 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
нет, достаточно создать DataModule.
ну, помимо того, что в DLL выполнится какая-то функция, надо вызвать, например, Prepare — которая создать модуль данных. затем — твою целевую функцию, а затем Free — которая освободит ресурсы. Prepare и Free тебе также надо разработать самой и также экспортировать из DLL. затем, сразу после LoadLibrary вызываешь Prepare, потом делаешь всё, что угодно, и перед FreeLibrary вызываешь Free.
|
|
Лена |
Отправлено: 22.11.2006, 18:42 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Теперь понятно. Сложное это дело DLL |
|
olegenty |
Отправлено: 22.11.2006, 18:46 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
не-а, как я раньше без них жил — ума не приложу. с ними намного упрощается
1. процесс разработки (при наличии внутреннего стандарта, хотябы интерфейса вызова. у меня каждая DLL экспортирует всего по 2 функции. Плагины — Execute и Free, Аддоны — Register и Unregister).
2. процесс сопровождения
|
|
Лена |
Отправлено: 22.11.2006, 19:03 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Почему простой путь не правильный?
CODE |
char * FindRecord(char *param)
{
TDataModule1 * DataModule1 = new TDataModule1(Application);
DataModule1->ADOQuery1->Active = false;
DataModule1->ADOQuery1->SQL->Clear();
sprintf(buf, "select code from key where code = \"%s\"", param);
DataModule1->ADOQuery1->SQL->Text = String(buf);
DataModule1->ADOQuery1->Active = true;
char *res = NULL;
if (DataModule1->ADOQuery1->RecordCount == 0)
;
else {
res = new char[DataModule1->ADOQuery1->FieldByName("code")->AsString.Length() + 1];
strcpy(res, DataModule1->ADOQuery1->FieldByName("code")->AsString.c_str());
}
DataModule1->ADOQuery1->Active = false;
char *res2 = res;
delete res;
delete DataModule1;
return res2;
}
|
то ошибка на рисунке:
и курсор поподает сюда:
__fastcall TDataModule1::TDataModule1(TComponent* Owner)
: TDataModule(Owner)
{
}
Отредактировано Лена — 22.11.2006, 19:18 |
|
Лена |
Отправлено: 22.11.2006, 19:18 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
рис
Присоединить изображение
|
|
Лена |
Отправлено: 22.11.2006, 19:42 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
У меня заработал такой вариант. Надежно так?
CODE |
char * FindRecord(char *param)
{
CoInitialize(NULL);
TDataModule1 * DataModule1 = new TDataModule1(Application);
DataModule1->ADOQuery1->Active = false;
DataModule1->ADOQuery1->SQL->Clear();
sprintf(buf, "select code from keys where code = '%s'", param);
DataModule1->ADOQuery1->SQL->Text = String(buf);
DataModule1->ADOQuery1->Active = true;
char *res = NULL;
char *res2 = NULL;
if (DataModule1->ADOQuery1->RecordCount == 0)
; // ничего не делать
else {
res = new char[DataModule1->ADOQuery1->FieldByName("code")->AsString.Length() + 1];
strcpy(res, DataModule1->ADOQuery1->FieldByName("code")->AsString.c_str());
res2 = strcpy(buf,res);
delete res;
}
DataModule1->ADOQuery1->Active = false;
delete DataModule1;
CoUninitialize();//это надо?
return res2;
}
|
Отредактировано Лена — 22.11.2006, 20:04 |
|