Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вставить форму в DLL, не показывая ее и не вызывая, вызов из DLL свойства объектов на форме 
V
    Опции темы
Bima
Дата 8.5.2007, 07:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Добрый день.
Сразу напишу, внизу смотрел ("А здесь смотрели?"). В основном там вызов из главной программы, формы, которая спрятана в DLL.

Ситуация такая: Есть код DLL на Visual C++. В него нужно вставить некоторые сетевые взаимодействия. Полностью программировать на  Visual C++, не то что бы не охота, просто все упирается в отсутствие сетевых протоколов и громоздкостью программного кода, который придется писать (если найти структуру протокола).
Поэтому решил сконвертировать код под ВСВ. Запустил мастер на ВСВ и сконвертировал код. Протестировал готовую DLL, все работает. Для вставки сетевых протоколов хочу использовать INDY (есть готовые примеры реализации).
Что бы создать хоть один динамический компонент INDY приходится  вставлять на форму такой же один компонет. Вот и хочу в проект вставить форму и пользоваться ее свойствами. Показывать я ее не буду, так что она нужна только для компонентов.

Сконвертированный код DLL такой:
dataserv.bpf:
Код

USEUNIT(".\dataserv.cpp");
USEFILE("vctobpr.log");
//---------------------------------------------------------------------------
#define DllEntryPoint

dataserv.cpp:
Код

//инклудовские файлы

// Главная рабочая нить  DLL, в которой должен происходить опрос
// устройства и обновление значений в массивах тегов:

void WorkingThread( void *dummy ) // Thread function
{
  while(1)
  { 
   //Опрос устройств (основной код программы)
  };
};

//---------------------------------------------------------------------------
// Класс, конструктор которого запускает рабочую нить DLL
// (это можно делать и из DLLEntryPoint по DLL_PROCESS_ATTACH,
// но через конструктор объекта, кажется, удобнее)

class MyWorkingThread
{
 public:

  MyWorkingThread() // Всю инициализацию dll делает конструктор:
  {
    //     Здесь инициализируются объекты DLL

    // Создаем рабочую нить:
    _beginthread( WorkingThread, 0, NULL );
  };
};

//=========================================================

/* 
   инициализация статического объекта, конструктор которого 
   сразу после загрузки DLL создает рабочую нить
   (чтобы не возиться с DLLEntryPoint - хотя это, конечно,
   дело разработчика):
*/
MyWorkingThread* mythread=new MyWorkingThread;


Для вставки формы я создал чистый проект и сохранил его в папке App. Потом открыл проект с DLL и вставил туда форму (из проекта App).
при сохранении проекта у меня получился файл dataserv.bpf вот таким:
Код

USEFORM("App\kod.cpp", Form1);

//---------------------------------------------------------------------------
#define DllEntryPoint

пришлось его поравить на прежний и вставить новую строку:
Код

USEUNIT(".\dataserv.cpp");
USEFORM("App\kod.cpp", Form1);
USEFILE("vctobpr.log");
//---------------------------------------------------------------------------
#define DllEntryPoint

при компиляции проекта выскакивала ошибка: [Linker Error] Unable to open file 'CONTROLS.RES'
я переменовал файл *.res из проекта App в CONTROLS.RES и после этого компиляция прошла успешно.

Но как бы я ни пытался использовать свойсва компонентов на форме, ничего у меня не получается. Компиляция проходит успешно, а на момент исполнения кода DLL все свойства неопределены. Догадываюсь, что форму нужно загрузить в память, но как??? Если делаешь проект с программой об этом не задумываешься, а здесь как???
P.S. DLL-ку писал не я


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Vyacheslav
Дата 8.5.2007, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Bima @  8.5.2007,  07:17 Найти цитируемый пост)
Показывать я ее не буду, так что она нужна только для компонентов.

Вообще то для таких веще предназначен TDataModule

Цитата(Bima @  8.5.2007,  07:17 Найти цитируемый пост)
Но как бы я ни пытался использовать свойсва компонентов на форме, ничего у меня не получается. Компиляция проходит успешно, а на момент исполнения кода DLL все свойства неопределены. Догадываюсь, что форму нужно загрузить в память, но как??? Если делаешь проект с программой об этом не задумываешься, а здесь как???

Это называется  -"высшее без среднего". Вы до сих по не знаете как создавать эксземпляры класса?
1. Создаем новый проект dll c использование VCl
2. Cоздаем  TDataModule, например TMyDataModule 
3. В нем реализуем весь неоюходимый нам фукционал
4. Пишем функцию
Код

//---------------------------------------------------------------------------
extern "C" __declspec(dllexport) TMyDataModule  * __stdcall CreateModule(TForm * mainForm)
{
    return new TMyDataModule( mainForm);
}



5 . При  работе грузим dll. Вызываем функцию CreateModule, которая возвращает нам экземпляр TMyDataModule и работаем с ним




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 8.5.2007, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Интересно выходит, а как мне отлаживать 2 Dll? 
Выходит так, что программа вызывает DLL (написанную на Visual C++), та в свою очередь вызывает DLL с VCL.
C TDataModule не работал, сейчас через поисковик начну собирать информацию


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Bima
Дата 8.5.2007, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Vyacheslav, есть просьба, напиши пример для реализации вот такого случая:

из Dll, нужно вызвать функцию (для примера test), которая возвращает случайное число(для примера).
как ее запихнуть в TDataModule и сделать DLL.

как потом ее вызвать из моей DLL-ки??? 

Облазил весь форум, что то ничего не нашел, в книгах Архангельского тоже что-то ничего не нашел :(




--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Vyacheslav
Дата 8.5.2007, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Код

class TMyDataModule : public TDataModule
{
...

public :
   int test(();
...

}  


Код

..
 
 TMyDataModule *(  *CreateModule)(TForm*);
  String DllName = "MyDll.dll";
  String  ProcName = "_CreateModule";

 try
 {
  HINSTANCE DllInstance;
 
#pragma warn -pia
  if (!(DllInstance = LoadLibrary(DllName.c_str())))
  {
   throw(Exception("Ошибка загрузки DLL:" + DllName));
  }
  if(!(CreateModule = ( TMyDataModule *(  *)(TForm*))
                 GetProcAddress(DllInstance,ProcName.c_str())))
  {
   throw(Exception("Ошибка получения адреса функции:"+ ProcName.c_str()));
  }
    TMyDataModule* module = CreateModule(this);
    int result = module->test();
 }
#pragma warn .pia
 catch(Exception& excp)
 {
  ShowErr(mtError,&excp);







--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 8.5.2007, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



ээээ.... ничего не понял :(

создал DLL:
код *.cpp такой:
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
   return 1;
}
//---------------------------------------------------------------------------
class TMyDataModule : public TDataModule
{
public :
   int test(void);
};
//---------------------------------------------------------------------------
int TMyDataModule::test(void)
{
return (int)random(100);
}
//---------------------------------------------------------------------------

Если честно, то я не понял зачем нужно создавать экземпляр класса, если на него ничего положить нельзя!!!
Скомпилил... все нормально

Что дальше делать???
второй код, я вообще его не могу никуда приладить :(. на первой строчке у меня выскакивает ошибка (у меня нет формы)
и так по каждой строке :(



--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Vyacheslav
Дата 8.5.2007, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



 Что ознаяаю точки в моем коде Вы догадываетесь?
Как добавлять TDataModule в dll Вы знаете? Как к TDataModule добавлять свои методы знаете? Я же Вам написал порядок созлания dll. Похоже Вы поняли и спросили как вызвать. Я Вам показал Вызов. А Вы в ответ в dll написали полную хрень

PS. Запомните раз и навсегда: класс и экземпляр класса разные вещи.То что Вы кладете на форму (дата модуль) - это Вы формируете класс. 
В приложении exe все формы попадают в список автосоздаваемых: это означает, что экземпляры объектов классов форм  будут созданы на автомате. см  Project->Option->Forms,  где показано, экземпляры для каких форм будут созданы автоматом, а какие не. (по умолчанию все создаются автоматом) . В dll экземпляры форм автоматом не создаются . Вы должны их создать с помощью new.  


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 10.5.2007, 06:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Цитата

Как добавлять TDataModule в dll Вы знаете?

нет, я же писал выше. На форуме не нашел.
Цитата

Как к TDataModule добавлять свои методы знаете?

то же нет, так как с TDataModule не работал.
Цитата

Похоже Вы поняли и спросили как вызвать. Я Вам показал Вызов. А Вы в ответ в dll написали полную хрень

возможно, я не разу не делал DLL, и не использовал TDataModule, поэтому и спросил совета.

Хорошо, не будем ходить вокруг да около... спрошу прямо, как переделать мою программу в DLL, в которой будет доступна всего лишь одна функция SendUdp???
 код программы, *.срр
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop

#include "Kod.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TIdUDPClient * MyUDP[10];
AnsiString MyHost[10];
int MyPort[10];
AnsiString MyText[10];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner){}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
for (int i=0; i<10; i++)   //создаем 10 компонетов UDP
   {
   MyUDP[i]=new TIdUDPClient(this);
   MyUDP[i]->BroadcastEnabled=false;
   MyUDP[i]->BufferSize=8192;
   MyUDP[i]->Name="MyUDP"+IntToStr(i);
   MyUDP[i]->ReceiveTimeout=-2;
   MyUDP[i]->Tag=i;
   MyUDP[i]->Active=false;
   }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete []MyUDP;    //Удаляем все компонеты UDP
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) //Пример для посылки по одному IP-адресу
{
MyHost[0]="127.0.0.1";
MyHost[1]="0"; //признак конца массива
MyPort[0]=5000;
MyText[0]="text01";
SendUdp(MyHost, MyPort, MyText); //Вызываем функцию отправки данных
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender) //Пример для посылки по двум IP-адресу
{
MyHost[0]="127.0.0.1";
MyHost[1]="127.0.0.1";
MyHost[2]="0"; //признак конца массива
MyPort[0]=5000;
MyPort[1]=5001;
MyText[0]="text11";
MyText[1]="text12";
SendUdp(MyHost, MyPort, MyText); //Вызываем функцию отправки данных
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender) //Пример для посылки по трем IP-адресу
{
MyHost[0]="127.0.0.1";
MyHost[1]="127.0.0.1";
MyHost[2]="127.0.0.1";
MyHost[3]="0"; //признак конца массива
MyPort[0]=5000;
MyPort[1]=5001;
MyPort[2]=5002;
MyText[0]="text21";
MyText[1]="text22";
MyText[2]="text23";
SendUdp(MyHost, MyPort, MyText);  //Вызываем функцию отправки данных
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdUDPServer1UDPRead(TObject *Sender, TStream *AData, TIdSocketHandle *ABinding)
{ //функция приема данных по 5000 порту
char *mydata;
int mylen;
mylen=AData->Size;
if (mylen==0) return;
mydata=new char[mylen];
AData->ReadBuffer(mydata,AData->Size);
Label1->Caption = mydata;
delete mydata;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdUDPServer2UDPRead(TObject *Sender, TStream *AData, TIdSocketHandle *ABinding)
{ //функция приема данных по 5001 порту
char *mydata;
int mylen;
mylen=AData->Size;
if (mylen==0) return;
mydata=new char[mylen];
AData->ReadBuffer(mydata,AData->Size);
Label2->Caption = mydata;
delete mydata;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdUDPServer3UDPRead(TObject *Sender, TStream *AData, TIdSocketHandle *ABinding)
{//функция приема данных по 5002 порту
char *mydata;
int mylen;
mylen=AData->Size;
if (mylen==0) return;
mydata=new char[mylen];
AData->ReadBuffer(mydata,AData->Size);
Label3->Caption = mydata;
delete mydata;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SendUdp(AnsiString *host, int *port, AnsiString *text)
{//Функция, которая посылает данные
int i=0;
while (host[i]!="0" & i<10)
   {
   MyUDP[i]->Host = host[i];
   MyUDP[i]->Port = port[i];
   MyUDP[i]->Active=true;
   MyUDP[i]->Send(text[i]);
   i++;
   }
}
//---------------------------------------------------------------------------

весь код программы представлен ниже.

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  UDP.rar 3,72 Kb


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Vyacheslav
Дата 10.5.2007, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Извините, я не собираюсь разбираться в Вашей программе.  

Цитата(Bima @  10.5.2007,  06:16 Найти цитируемый пост)
нет, я же писал выше. На форуме не нашел.

Вы не не нашли ?  smile   
Цитата(Vyacheslav @  8.5.2007,  10:10 Найти цитируемый пост)
1. Создаем новый проект dll c использование VCl
2. Cоздаем  TDataModule, например TMyDataModule 
3. В нем реализуем весь неоюходимый нам фукционал
4. Пишем функцию

Ну если Вы не в состоянии найти необходимые  кнопки в С++ Builder и пользоваться хелпом
то пошагам
1. File->New->Other-> Dll WIzard
2. File->New->Other->DataModule
   Переименовываем его , например, в TMyDataModule  
3. На всякий случай, если Вы не умеете руками добавлять свои методы к классам, то
  View->Class Explorer ->клик правой кнопкой на классе TMyDataModule -> New Method
  Далее заполняем все что нужно.   На DataModule кладем все нужные нам компоненты и 
  пишем релизацию наших методов
4. Пишем  ручками 
Код

---------------------------------------------------------------------------
extern "C" __declspec(dllexport) TMyDataModule  * __stdcall CreateModule(TForm * mainForm)
{
    return new TMyDataModule( mainForm);
}

6. В exe вставлем код по загрузке и вызову CreateModul, получаем экземпляр TMyDataModule и вызываем нужные на методы



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 10.5.2007, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Цитата

Пишем  ручками

Простите за назойливый вопрос, где писать???
Пока остановился на данном шаге.
сделал как сказано, получил следующее:
Код DLL *.cpp
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
   return 1;
}
//---------------------------------------------------------------------------

код DataModule *.срр
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TTMyDataModule *TMyDataModule;
TIdUDPClient * MyUDP[10];
//---------------------------------------------------------------------------
__fastcall TTMyDataModule::TTMyDataModule(TComponent* Owner):TDataModule(Owner)
{
for (int i=0; i<10; i++)   //создаем 10 компонетов UDP
   {
   MyUDP[i]=new TIdUDPClient(this);
   MyUDP[i]->BroadcastEnabled=false;
   MyUDP[i]->BufferSize=8192;
   MyUDP[i]->Name="MyUDP"+IntToStr(i);
   MyUDP[i]->ReceiveTimeout=-2;
   MyUDP[i]->Tag=i;
   MyUDP[i]->Active=false;
   }
}
//---------------------------------------------------------------------------
__fastcall TTMyDataModule::SendUdp(AnsiString * host, int * port, AnsiString * text)
{
int i=0;
try{
   while (host[i]!="0" & i<10)
      {
      MyUDP[i]->Host = host[i];
      MyUDP[i]->Port = port[i];
      MyUDP[i]->Active=true;
      MyUDP[i]->Send(text[i]);
      i++;
      }
   }
catch(...)
   {
   return -1;
   }
return 0;
}
//---------------------------------------------------------------------------

хейдер DataModule *.h
Код

//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdUDPBase.hpp>
#include <IdUDPClient.hpp>
//---------------------------------------------------------------------------
class TTMyDataModule : public TDataModule
{
__published:    // IDE-managed Components
   TIdUDPClient *IdUDPClient1;
private:    // User declarations
public:        // User declarations
   __fastcall TTMyDataModule(TComponent* Owner);
   __fastcall SendUdp(AnsiString * host, int * port, AnsiString * text);
};
//---------------------------------------------------------------------------
extern PACKAGE TTMyDataModule *TMyDataModule;
//---------------------------------------------------------------------------
#endif

Догадываюсь, что нужно, что то вставить в хейдер самой DLL, то есть декларацию моих экспортируемых функций, но вот как... ума не приложу...

если брать образец из книги Архангельского, то нужно написать примерно так:
Код

#ifndef  _UFIND_H
#define  _UFIND_H

#ifdef __DLL__
#define DLL_EI __declspec(dllexport)
#else
#define DLL_EI __declspec(dllimport)
#endif

extern "C" int DLL_EI SendUdp(AnsiString * host, int * port, AnsiString * text)
#endif

но я не уверен в правильности написания да и возвращаемое значение (int) не знаю нужно ли???



--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Vyacheslav
Дата 10.5.2007, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Bima @  10.5.2007,  13:58 Найти цитируемый пост)
Простите за назойливый вопрос, где писать???

В любом Вам удобном месте. Ну например перед реализацией конструктора модуля.
Если сделать вот так, то никакой хидер Вам в exe не понадобится
Код Application c одной формой и кнопкой
Код

include <vcl.h>
#pragma hdrstop

#include "Unit3.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm3 *Form3;
//---------------------------------------------------------------------------
__fastcall TForm3::TForm3(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm3::Button1Click(TObject *Sender)
{
   void (  *RunTest)(TForm*);
  String DllName = "Project1.dll";
  String  ProcName = "RunTest";

 try
 {
  HINSTANCE DllInstance;
 
#pragma warn -pia
  if (!(DllInstance = LoadLibrary(DllName.c_str())))
  {
   throw(Exception("Ошибка загрузки DLL:" + DllName));
  }
  if(!(RunTest = ( void (  *)(TForm*))
                 GetProcAddress(DllInstance,ProcName.c_str())))
  {
   throw(Exception("Ошибка получения адреса функции:"+ ProcName));
  }
    RunTest(this);

 }
#pragma warn .pia
 catch(Exception& excp)
 {
  Application->ShowException(&excp);
 }
}
//---------------------------------------------------------------------------



DLL:
хидер
Код

//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>


//---------------------------------------------------------------------------
class TMyDataModule : public TDataModule
{
__published:    // IDE-managed Components
private:    // User declarations
public:        // User declarations
    __fastcall TMyDataModule(TComponent* Owner);
     void test();
};
//---------------------------------------------------------------------------


cpp
Код

pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMyDataModule *MyDataModule = NULL;

extern "C" __declspec(dllexport) void __stdcall RunTest(TForm * mainForm)
{
     if (!MyDataModule) {
         MyDataModule  =   new TMyDataModule( mainForm);
     }
    MyDataModule->test();
}

//---------------------------------------------------------------------------
__fastcall TMyDataModule::TMyDataModule(TComponent* Owner)
    : TDataModule(Owner)
{
}
//---------------------------------------------------------------------------


void TMyDataModule::test()
{
    ShowMessage("Call method test from dll");
}






--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 10.5.2007, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



:(
ничего не выходит :( , хотя делал как написали.
вот код DLL *.cpp
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
   return 1;
}
//---------------------------------------------------------------------------

код DataModule *.cpp
Код

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TTMyDataModule *TMyDataModule;
TIdUDPClient * MyUDP[10];
TForm * mainForm;//не знаю зачем, но без него не работает ???
extern "C" __declspec(dllexport) int __fastcall SendUdp(AnsiString * host, int * port, AnsiString * text)
{
if (!TMyDataModule) {
    TMyDataModule = new TTMyDataModule(mainForm); //вставляю ненужный указатель
     }
return SendUdp(host, port, text);
}

//---------------------------------------------------------------------------
__fastcall TTMyDataModule::TTMyDataModule(TComponent* Owner):TDataModule(Owner)
{
for (int i=0; i<10; i++)   //создаем 10 компонентов UDP
   {
   MyUDP[i]=new TIdUDPClient(this);
   MyUDP[i]->BroadcastEnabled=false;
   MyUDP[i]->BufferSize=8192;
   MyUDP[i]->Name="MyUDP"+IntToStr(i);
   MyUDP[i]->ReceiveTimeout=-2;
   MyUDP[i]->Tag=i;
   MyUDP[i]->Active=false;
   }
}
//---------------------------------------------------------------------------
int __fastcall TTMyDataModule::SendUdp(AnsiString * host, int * port, AnsiString * text)
{
int i=0;
try{
   while (host[i]!="0" & i<10)
      {
      MyUDP[i]->Host = host[i];
      MyUDP[i]->Port = port[i];
      MyUDP[i]->Active=true;
      MyUDP[i]->Send(text[i]);
      i++;
      }
   }
catch(...)
   {
   return -1;
   }
return 0;
}
//---------------------------------------------------------------------------

код DataModule *.h
Код

//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdUDPBase.hpp>
#include <IdUDPClient.hpp>
//---------------------------------------------------------------------------
class TTMyDataModule : public TDataModule
{
__published:    // IDE-managed Components
   TIdUDPClient *IdUDPClient1;
private:    // User declarations
public:        // User declarations
   __fastcall TTMyDataModule(TComponent* Owner);
   int __fastcall SendUdp(AnsiString * host, int * port, AnsiString * text);
};
//---------------------------------------------------------------------------
extern PACKAGE TTMyDataModule *TMyDataModule;
//---------------------------------------------------------------------------
#endif


Пытался сделать программу, где подсоединяю DLL. на форме кнопка и Label.
вот код:
*.cpp
Код

//---------------------------------------------------------------------------
#include <vcl.h>
#include <except.h>
#include <SysUtils.hpp>
#pragma hdrstop

#include "kod.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
AnsiString MyHost[10];
int MyPort[10];
AnsiString MyText[10];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner){}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MyHost[0]="127.0.0.1";
MyHost[1]="0"; //  
MyPort[0]=5000;
MyText[0]="text01";
HINSTANCE DllInstance;

typedef  int (__import * Send_Udp(AnsiString *, int *, AnsiString *));
Send_Udp * SendUdp = NULL;

try
   {
   DllInstance = LoadLibrary("Project1.dll");
   if (DllInstance)
      SendUdp = (Send_Udp *) GetProcAddress(DllInstance,"_SendUdp");
   if (SendUdp)
      SendUdp(MyHost, MyPort, MyText); // функция отправки данных  
   }
catch(...)//catch(Exception& excp)   :( не работает эта инструкция
   {
   Application->MessageBox(0,"Error",MB_ICONERROR);
   }
}
//---------------------------------------------------------------------------

хейдер формы
Код

//---------------------------------------------------------------------------
#ifndef kodH
#define kodH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
   TButton *Button1;
   TLabel *Label1;
   void __fastcall Button1Click(TObject *Sender);
private:    // User declarations
public:        // User declarations
   __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


При нажатии на кнопку ничего не происходит. Пытался смотреть со стороны DLL (пускал ее в режиме отладке, там она вообще не вызывается) :(

Это сообщение отредактировал(а) Bima - 11.5.2007, 05:35


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Bima
Дата 11.5.2007, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Решил проблему.

Взял пример из книги, переделал его под свой и получил DLL, которую статически подключаю к форме.

в примере правда используется не DataModule, а обыкновенная форма.


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Vyacheslav
Дата 11.5.2007, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Bima @  10.5.2007,  14:54 Найти цитируемый пост)
ничего не выходит :( , хотя делал как написали.

Это Вы загнули. Вы сделали не так. Для начала Вам просто стоило взять все один к одному, а дальше приводить к своему варианту. Но Вы же крутой программист smile
Код

try
   {
   DllInstance = LoadLibrary("Project1.dll");
   if (DllInstance)
      SendUdp = (Send_Udp *) GetProcAddress(DllInstance,"_SendUdp");
   if (SendUdp)
      SendUdp(MyHost, MyPort, MyText); // функция отправки данных  
   }
catch(...)//catch(Exception& excp)   :( не работает эта инструкция
   {
   Application->MessageBox(0,"Error",MB_ICONERROR);
   }
}



Зачем было в try/cath обрамялть, если Вы выкинули генерацию исключений. А если бы Вы их оставили, то Вам было сообщено, что функция _SendUdp не найдена.

А вот это вообще маразм
Код

TForm * mainForm;//не знаю зачем, но без него не работает ???
...

if (!TMyDataModule) {
    TMyDataModule = new TTMyDataModule(mainForm); //вставляю 


Извините, но у меня возникает такое ощущение, что не даже пытаетесь осмыслить, что пишут Вам и что Вы сами пишите



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Bima
Дата 11.5.2007, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 518
Регистрация: 15.8.2006

Репутация: 2
Всего: 2



Цитата

Это Вы загнули. Вы сделали не так. Для начала Вам просто стоило взять все один к одному, а дальше приводить к своему варианту. Но Вы же крутой пронраммист 

Как раз я так и делал(все скопиовал один в один). Я конечно понимаю, что вам трудно было написать весь код, поэтому вы кусками из своей программы давали код или из памяти (тут я не телепат), но то, что я один в один сделал, как было написано - не заработало. Я сначала подумал, что хейдеров нужных нет, и начал копаться в справке, но после вставки нужных, компилятор упорно не хотел понимать catch(Exception& excp) и подобные вещи.
Цитата

А если бы Вы их оставили, то Вам было сообщено, что функция _SendUdp не найдена.

Это самый последний мой вариант, который я тестировал в два часа ночи. Поэтому я не стал его править, а просто выложил сюда. До этого у меня там было написано SendUdp, который кстати тоже не заработал. 
Цитата

Извините, но у меня возникает такое ощущение, что не даже пытаетесь осмыслить, что пишут Вам и что Вы сами пишите

Я бы может и понял, если бы коментарии были, а так половина кода, для меня была темным лесом, хоть и пытался в нем честно разобраться.
для примера вот этот код:
Код

extern "C" __declspec(dllexport) void __stdcall RunTest(TForm * mainForm)
{
     if (!MyDataModule) {
         MyDataModule  =   new TMyDataModule( mainForm);
     }
    MyDataModule->test();
}

То есть, как я понимаю, для создания TMyDataModule нужен указатель на форму, который используется в функции.... А если мне параметры нужно передать???
А если у меня несколько функций. Может для вас этот код очень легкий, но для меня он совершенно не прозрачный и взглянув на него через год, я буду думать, а что я здесь накуралесил, а какой здесь алгоритм???

В результате всего TMyDataModule для меня так и остался загадкой, с которой я бы хотел разобраться, и пришлось делать более простые алгоритмы(хоть и не такие эффективные), которые я взял из книжки.


--------------------
Чтобы дойти до цели, надо идти.

Клавиатура и мышь - это главные инструменты прогресса.
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0905 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.