Помощь - Поиск - Пользователи - Календарь
Полная версия: Dll.
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
Fanat
Хочу создать файл Dll. Делаю так File->New->Other->Dll wizard
Там забиваю:

#include <windows.h>
extern "C" __declspec(dllexport)
double AddNumbers(double a, double b)
{
return a + b;
}



Помимо этого там ещё есть функция аналог main. Как правильно сохранить? Я жму сохранить и сам подписываю после точки расширение .dll... После чего открыть этот файл заново не получаеться.
Нам ещё сказали на занятиях что автоматически должен создаться файл .lib? И зачем он мне ещё предлогает сохранить проект какойто который я не создавал?...


volvo
Что я только что сделал:

Открыл Билдер, File -> New -> Other -> Dynamic Link Library...

В диалоговом окне отключил все примочки VCL и Multi-Threading-а, сделал язык не С++, а С.

Открывается редактор:

#include <windows.h>

// Тут много букв - это пока неважно ...

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------



Добавляю, собственно, твою функцию... Получаю такой файл:

#include <windows.h>

#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif


double DLL_EXPORT AddNumbers(double a, double b)
{
return a + b;
}

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}

Сохраняю этот проект, причем файл сохраняется с расширением *.С... Билдим проект - получаем DLL вместо EXE...
Fanat
Сделал так. Получил .dll.
Теперь в другом проекте.



#include <windows.h>
#include <stdio.h>
#define BUILD_DLL

//...

void __fastcall TForm1::Button1Click(TObject *Sender)
{
typedef int(*importFunction)(int, int);

importFunction addNumbers;
int result;

HINSTANCE hinstLib = LoadLibrary("Project2.dll");
addNumbers = (importFunction)GetProcAddress(hinstLib, "AddNumbers");

result = addNumbers(1, 2);
Edit1->Text=IntToStr(result);

FreeLibrary(hinstLib);
}



Что то не так. Файл Project2.dll лежит в тойже папке что и файлы этого проекта.
volvo
DLL:


#include <windows.h>

double __declspec(dllexport) CALLBACK AddNumbers(double a, double b)
{
return a + b;
}

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}



Проект:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
typedef double(CALLBACK *importFunction)(double, double);

importFunction addNumbers;
int result;

HINSTANCE hinstLib = LoadLibrary("Project2.dll");
addNumbers = (importFunction)GetProcAddress(hinstLib, "AddNumbers");

result = addNumbers(1, 2);
Edit1->Text=IntToStr(result);
FreeLibrary(hinstLib);
}

Все работает...
Fanat
Спсибо разобрался... smile.gif
Fanat
А если необходимо создать .dll в котором описаны методы класса...это как сделать?...
Надо ли изменять или создавать файл .h или что то похожее?..
volvo
Ничего не надо ни изменять ни создавать заново. Один и тот же H-файл может использоваться и для DLL, и для использующей ее программы. Только в DLL класс должен описываться как

class __declspec (dllexport) MyClass {
...
};

а в программе - как
class __declspec (dllimport) MyClass {
...
};
(элементарно делается с использованием #ifdef)
Fanat
Пишу в файле который хочу чтобы был .dll с описанием методов класса.

  
// #include "A.h"
// class __declspec(dllimport) A; Что то из этого нужно?

extern "C" __declspec(dllexport)
void A::setC(int anC)
{
C=anC;
};



Тогда в A.h (тот который должен относиться к .dll) что должно быть?


class __declspec(dllexport) A
{
public:
virtual void setC(int anC);
private:
int C;
};

volvo
Используя LoadLibrary ты замучаешься работать с классом из DLL. Вот тут лежит пример, посмотри:
http://www.codeproject.com/dll/classesexportedusingLL.asp

Гораздо проще работать с LIB-файлом. Для этого случая:

Подключаемый к DLL-проекту header:
class __declspec(dllexport) MyClass {

public:
MyClass(int);
virtual void setConsumerID(int);
int getConsumerID();
private:
int ConsumerID;

};


В подключаемом к основному проекту заменить dllexport на dllimport
Собственно, код библиотеки:

#include <windows.h>
#include "MyClass.h"

MyClass::MyClass(int value) {
ConsumerID = value;
}
void MyClass::setConsumerID(int value) {
ConsumerID = value;
}
int MyClass::getConsumerID() {
return ConsumerID;
}


#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}



Использование (подключаем H-файл с описанием класса и LIB-файл через "Project -> AddToProject -> имя_файла.LIB"):
void __fastcall TForm1::Button1Click(TObject *Sender)
{

MyClass my(10);
ShowMessage(IntToStr(my.getConsumerID()));
}
Fanat
Сделал как ты написал. Спасибо работает. Но является ли это динамической загрузкой.
Исходя из примера пишу HMODULE hMod = LoadLibrary ("ProjectDll.dll") выдаёт ошибку.
Как её загрузить?

Пишу так:


{
typedef int (*importFunction)();
importFunction getConsumer;
HMODULE hMod = LoadLibrary ("ProjectDll.dll");//<--Или .lib?
getConsumer = (importFunction)GetProcAddress(hMod, "getConsumer");
MyClass my(10);
ShowMessage(IntToStr(my.getConsumerID()));
}


volvo
Вообще-то с LoadLibrary проблем быть не должно. У меня по крайней мере оно работает... А вот getConsumer - нулевой...

А это:
...
MyClass my(10);
...

работать не будет, потому как тело конструктора описано тоже в библиотеке, и надо брать адрес конструктора (и вызывать его по адресу), чтобы инициализировать объект.
Fanat
Цитата(volvo @ 21.10.2007 18:29) *

работать не будет, потому как тело конструктора описано тоже в библиотеке, и надо брать адрес конструктора (и вызывать его по адресу), чтобы инициализировать объект.


А как конструктор описать и взять по адресу?
Пробовал через указатели сделать, но никак не получаеться wacko.gif
volvo
Вот тут есть довольно подробное объяснение процесса (и альтернативы тоже)...
Fanat
Цитата(volvo @ 21.10.2007 19:50) *

Вот тут есть довольно подробное объяснение процесса (и альтернативы тоже)...


Во...спасибо...3ий вариант ето то что нужно...а с помощью чего можно открыть файл который разопхивируеться?.. Я так понимаю там пример...он бы мне сильно помог...=)
volvo
blink.gif У меня третьим WinRar-ом свободно открылся...
Fanat
Цитата(volvo @ 21.10.2007 20:53) *

blink.gif У меня третьим WinRar-ом свободно открылся...


Я в смысле тот файл что внутри лежит...
volvo
А что там внутри у тебя не открывается? BPR - файлы проекта, открывай их и компилируй DLL-ку и саму программу...
Fanat
Цитата(volvo @ 21.10.2007 21:22) *

А что там внутри у тебя не открывается? BPR - файлы проекта, открывай их и компилируй DLL-ку и саму программу...


Просто мне почему то пришлось дважды его разорхивировать и появились все файлы...
Fanat
Всё!!! good.gif ...у меня получилось...спасибо огромное...только вопрос один:
откуда вообще в процессе работы программы берёться то что необходимо обратиться к файлу
КлассНаследник.cpp ведь ни один файл его не включает в себя?..
volvo
Цитата
ни один файл его не включает в себя?

FormTestDLL.H:

typedef IMyCls * (__declspec(dllimport) FCreate(int Size));
...
class TfrmTestDll : public TForm {
...
FCreate * Create; // <--- это что по-твоему?
...
};
Fanat
Цитата(volvo @ 21.10.2007 23:34) *

FormTestDLL.H:

typedef IMyCls * (__declspec(dllimport) FCreate(int Size));
...
class TfrmTestDll : public TForm {
...
FCreate * Create; // <--- это что по-твоему?
...
};



Это обьявление указателя на FCreate. А FCreate это ???

Ну а FCreate это вроде функтор.
volvo
Если честно - я не понял, что тебя смущает вообще... У тебя же в DLL создается экземпляр класса-наследника (т.е., MyCls). То, что указатель на него приводится к указателю на предка (то есть, к IMyCls *) - это тебя смущает?
Fanat
Цитата(volvo @ 21.10.2007 23:55) *

Если честно - я не понял, что тебя смущает вообще... У тебя же в DLL создается экземпляр класса-наследника (т.е., MyCls). То, что указатель на него приводится к указателю на предка (то есть, к IMyCls *) - это тебя смущает?


Это не смущает. Смущало то что файл MyCls.cpp нигде не подключался...а он собственно и в обычных программах нигде не поключаеться...

Теперь всё понятно...ещё раз спасибо...
volvo
Как это "не подключается?"

А в DBTEST.BPR что такое:
Цитата
<VERSION value="BCB.05.03"/>
<PROJECT value="&quot;F:\PROJECTS\Cut Expert\DBTEST2\bin\dbtest.dll&quot;"/>
<OBJFILES value="obj\dbm.obj obj\mycls.obj"/>

в нижней строке? smile.gif Файл подключается к проекту и участвует в сборке библиотеки...
Fanat
То есть таким образом он подключаеться. Буду знать.
Fanat
Вот прочитал help на который ты давал ссылку...
откуда взяться файлу .def?..самому создать?..
И как узнать как назвал компилятор мою функцию?..
volvo
Цитата
откуда взяться файлу .def?
Сбрось свою DLL-ку в каталог \BIN в папке Builder-а, и запусти
Цитата(Console)
E:\Program Files\Borland\BDS\4.0\Bin>impdef project.def project3.dll
(ну, со своим именем DLL естественно)

В результате в той же папке появляется файл project.def, который содержит, например, такое:
LIBRARY     PROJECT3.DLL

EXPORTS
@MyClass@$bctr$qi @1 ; MyClass::MyClass(int)
@MyClass@getConsumerID$qv @3 ; MyClass::getConsumerID()
@MyClass@setConsumerID$qi @2 ; MyClass::setConsumerID(int)
@std@nothrow @5 ; std::nothrow
___CPPdebugHook @4 ; ___CPPdebugHook
В первом столбце - то, что тебе нужно...
Fanat
Это через DOS в смысле?
Он ругаеться на то что Program Files отдельно написано...
volvo
Это через Start -> Run -> CMD ...

то, что до знака ">" - это системное приглашение, тебе надо войти в папку \BIN... А там уже напечатать то, что выделено красным...
Fanat
Цитата(volvo @ 22.10.2007 22:07) *

Это через Start -> Run -> CMD ...

то, что до знака ">" - это системное приглашение, тебе надо войти в папку \BIN... А там уже напечатать то, что выделено красным...


Так я так и делал...только он мне не даёт переместиться в папку Program Files...потому что написание раздельное...
volvo
Возьми в кавычки... То есть,
CD "диск_на_котором_у_тебя_билдер:\Program Files\Borland\ну_и_дальше_путь_к_папке" должно дать то же результат...
Fanat
Получил. Так теперь можно задать имя функции своё?

Код
LIBRARY     TWOFUNCPROJECT.DLL

EXPORTS
    @Create$qv                     @1  ; Create()


Переместить этот файл в папку где находиться проект dll и потом заново build?..
volvo
Цитата
Так теперь можно задать имя функции своё?
Никак... Тебе это не нужно. Все что тебе может понадобиться - взять отсюда имя, и использовать его в программе, если тебе нужно сделать GetProcAddress...
Fanat
Понянто...спасибо...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.