Страница 1 из 1

Создание dll библиотеки и её динамическое подключение....

Добавлено: 17 ноя 2005, 21:02
Mike_3000
Подскажите плиз, у меня такой вопрос, что-то не могу найти на него ответ: :?:
Мне необходимо с помощью C++ Builder создать динамическую dll библиотеку со своей функцией. А затем, чтобы в программе, уже откомпелированной (exe-шнике) мог ввести путьк ней и эта библиотека бы подключилась и я мог использовать функцию описанную ней...
Подскажите, буду очень признателен...

Добавлено: 17 ноя 2005, 22:11
Mihij
Если этого не было предусмотрено заранее, то возможно и никак. Единственное решение пройтись деассембером, получить исходный код и перекомповать уже с новой бибиотекой.

Re: Создание dll библиотеки и её динамическое подключение...

Добавлено: 17 ноя 2005, 23:06
BreakPointMAN
Что значит фраза
Mike_3000 писал(а):А затем, чтобы в программе, уже откомпелированной (exe-шнике) мог ввести путьк ней и эта библиотека бы подключилась и я мог использовать функцию описанную ней...
:?:

Добавлено: 18 ноя 2005, 17:10
Eugie
Mike_3000, опиши подробнее ситуацию. В exe-шнике подразумевается динамическое подключение DLL (c помощью LoadLibrary)?

Добавлено: 21 ноя 2005, 19:39
Mike_3000
Извените, видимо действительно на полностью изложил ситуацию. Я только начал писать на C++, и мне надо написать программу, в которой будут использоваться функции которые должны быть записаны в dll. Т.е. в рабочем состоянии (exe-шнике) есть кнопка, в которой открываеться OpenDialog и я выбираю путь к dll-ке которую надо подключить. :(

Добавлено: 22 ноя 2005, 16:40
WinMain
В чём конкретно твоя проблема?
а. Создание DLL-модуля?
б. Его загрузка из приложения?
в. Вызов стандартного окна диалога?

Или ещё что-то?

Добавлено: 22 ноя 2005, 16:52
Eugie
1) Создай DLL с помощью DLL Wizard, начини ее своими функциями и объяви их экспортируемыми (как это сделать, см. ссылку в конце поста).

2) На форму положи кнопку Load и компонент типа TOpenDialog.

3) Определи глоб.переменную для дескриптора загружаемой библиотеки:

Код: Выделить всё

  HMODULE gLib;
3) Задай для кнопки обработчик:

Код: Выделить всё

void __fastcall TForm1::LoadClick(TObject *Sender)
{
  OpenDialog1->DefaultExt = "DLL";
  OpenDialog1->FileName = "*.dll";
  OpenDialog1->Filter = "Dynamic-link libraries|*.DLL";
  // C помощью станд.диалога Open находим нужную DLL
  if (OpenDialog1->Execute())
  {
     // Пытаемся загрузить ее
     gLib = LoadLibrary(OpenDialog1->FileName);
     if (!gLib) 
       MyErrorHandler();// сообщаем об ошибке
  }
}
4) Теперь, если DLL удалось загрузить, можно вызывать экспортируемые ею функции. Примерно так:

Код: Выделить всё


// Предположим, что в DLL есть такая функция: String _declspec(dllexport) __stdcall HelloFunc(void) { return "Hello, buddy!"; }
typedef String __stdcall (*MySimpleFunc)(void);
...
// Динамический вызов:
MySimpleFunc func;
if (gLib)
{
  func = (MySimpleFunc)GetProcAddress(gLib,"_HelloFunc"); // Зам.: С++ Builder добавляет подчеркивание в имена всех экспортируемых функций
  if (func) // если есть такая функция в загруженной DLL
    Label1->Caption = func();  // вызываем ее
}
5) Когда DLL больше не нужна, выгружаем ее из памяти:

Код: Выделить всё

  FreeLibrary(gLib);
В общем, схема примерно такая. Вот еще ссылка, там изложено подробнее: http://v3ps.narod.ru/ru/programming/cpp ... create.htm

Добавлено: 25 ноя 2005, 20:47
Mike_3000
Пасиб отчасти помогло, но всё равно до конца не получаеться:
поступаю таким образом
Создаю dll в С++
файл rmn.cpp:

Код: Выделить всё

#include <vcl.h>
#include <windows.h>
#pragma hdrstop


#pragma argsused
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
switch(fwdreason)
  {
   case DLL_PROCESS_ATTACH:
    if(lpvReserved)
     MessageBox(NULL, "Ïðîöåññ ïîäêëþ÷èë DLL ñòàòè÷åñêè", "DLLMain", MB_OK);
    else
     MessageBox(NULL, "Ïðîöåññ ïîäêëþ÷èë DLL äèíàìè÷åñêè", "DLLMain", MB_OK);
    break;

   case DLL_PROCESS_DETACH:
    MessageBox(NULL, "Ïðîöåññ îòêëþ÷èë DLL", "DLLMain", MB_OK);
    break;

   case DLL_THREAD_ATTACH:
    MessageBox(NULL, "Òðýéä ïîäêëþ÷èë DLL ñòàòè÷åñêè", "DLLMain", MB_OK);
    break;

   case DLL_THREAD_DETACH:
    MessageBox(NULL, "Òðýéä îòêëþ÷èë DLL", "DLLMain", MB_OK);
    break;

}
        return 1;

}


float MyFunc(float x)
{
 float y = 0;
 y = x*x;
 return y;
}


 
содеражание rmn.h

Код: Выделить всё

#ifndef __RMN_H
#define __RMN_H

#if defined(__cplusplus)
extern "C"
{
#endif
__declspec(dllexport) float MyFunc(float x);

#if defined(__cplusplus)
}
#endif

#endif //__RMN_H
Нажимаю Build, библиотеку делает всё впорядке, а вот терь пытаюсь подключить библиотечку и использовать функцию:
пишу :

Код: Выделить всё


void __fastcall TForm1::Button1Click(TObject *Sender)
{
HMODULE gLib;
MySimpleFunc func;
gLib = LoadLibrary("rmn.dll");
if (gLib)
{
  func = (MySimpleFunc)GetProcAddress(gLib,"_MyFunc"); 
  if (func) 
    Label1->Caption = FloatToStr(func(2));  }
}

В заголовочном файле прописано

Код: Выделить всё

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Dialogs.hpp>
//---------------------------------------------------------------------------
typedef float __stdcall (*MySimpleFunc)(float);



class TForm1 : public TForm
{
__published:	// IDE-managed Components
        TEdit *Edit1;
        TButton *Button1;
        TLabel *Label1;
        TButton *Button2;
        TOpenDialog *OpenDialog1;
        void __fastcall Button1Click(TObject *Sender);
private:	// User declarations
HINSTANCE DllHandle;
public:		// User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Dll подключает а функцию не видит. ПОдскажите, плз, что я не так делаю :(

Добавлено: 25 ноя 2005, 21:49
Eugie
Воспользуйся утилитой impdef.exe из $(BCB)\Bin (она строит .def-файл для dll) и посмотри имя экспортируемой функции. Синтаксис impdef.exe rmn.def rmn.dll, примерный вид .def-файла:

Код: Выделить всё

LIBRARY RMN.DLL

EXPORTS
    MyFunс @1 ;
Здесь вместо MyFunc может стоять _MyFunc или что-то еще - это экспортируемое имя твоей функции (а @1 - ее порядковый номер, можно обращаться и по нему). Это имя и нужно передать в GetProcAddress().

Можно сделать проще: опиши прототип своей функции (в RMN.H):

Код: Выделить всё

extern "C" 
{
  float __declspec(dllexport) __stdcall MyFunc(float x);
}
- тогда экспортируемое имя будет просто "MyFunc", без дополнительных украшений.

Но советую все же разбраться, как работать с DLL, что такое статическая и динамическая загрузка - пригодится в дальнейшей программерской работе/учебе :) На RSDN есть хорошая статья по DLL http://www.rsdn.ru/article/devtools/bcbdll.xml
И пусть "прикладное" название не смущает, там вопрос рассмотрен достаточно широко.