Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Создание и использование DLL / 9 сообщений из 9, страница 1 из 1
31.01.2007, 13:00
    #34295840
Ivan Aleksandrovich
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание и использование DLL
Всех приветствую.
Я недавно начал программировать на С++ и вот понадобилось создать DLL, но при запуске приложения, использующего созданную библиотеку возникает ошибка и приложение аварийно закрывается. Подскажите, пожалуйста, что не так.
Программирую в DevCpp.
Создал простейшую DLL:
dllmain.cpp:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
DLLIMPORT int HelloWorld (int i1,int i2)
{
	return(i1+i2);
}

BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:
        break;
      case DLL_PROCESS_DETACH:
        break;
      case DLL_THREAD_ATTACH:
        break;
      case DLL_THREAD_DETACH:
        break;
    }
    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}
Заголовок dll.h:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */

DLLIMPORT int HelloWorld (int i1,int i2);

#endif /* _DLL_H_ */

Вот код программы, использующей DLL (dll.h - это тот же файл) uselibr.cpp:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include "libr/dll.h"

using namespace std;
typedef int (*func1)(int i1,int i2);
int (APIENTRY *DllFun) (int i1,int i2);

int main(int argc, char *argv[])
{
func1 Mess;
	int i=Mess( 1 , 2 );
	cout << "Mess = " << i << endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}
Ошибка возникает при вызове Mess.
Прошу помощи. И благодарен за ответы
...
Рейтинг: 0 / 0
31.01.2007, 13:43
    #34296048
Создание и использование DLL
Ivan AleksandrovichВсех приветствую.
Я недавно начал программировать на С++ и вот понадобилось создать DLL, но при запуске приложения, использующего созданную библиотеку возникает ошибка и приложение аварийно закрывается. Подскажите, пожалуйста, что не так.
Программирую в DevCpp.
Создал простейшую DLL:
dllmain.cpp:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
DLLIMPORT int HelloWorld (int i1,int i2)
{
	return(i1+i2);
}

BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:
        break;
      case DLL_PROCESS_DETACH:
        break;
      case DLL_THREAD_ATTACH:
        break;
      case DLL_THREAD_DETACH:
        break;
    }
    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}
Заголовок dll.h:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */

DLLIMPORT int HelloWorld (int i1,int i2);

#endif /* _DLL_H_ */

Вот код программы, использующей DLL (dll.h - это тот же файл) uselibr.cpp:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include "libr/dll.h"

using namespace std;
typedef int (*func1)(int i1,int i2);
int (APIENTRY *DllFun) (int i1,int i2);

int main(int argc, char *argv[])
{
func1 Mess;
	int i=Mess( 1 , 2 );
	cout << "Mess = " << i << endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}
Ошибка возникает при вызове Mess.
Прошу помощи. И благодарен за ответы
Ну так нету у тебя функции Mess... И никакой другой функции нет по этому адресу...
Это то же самое, что работать с массивом через указатели...

По-моему, должно быть так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
#include <cstdlib>
....
//здесь ничего не меняем...
...

int main(int argc, char *argv[])
{
        func1 Mess;
        Mess=HelloWorld;
	int i=Mess( 1 , 2 );
	cout << "Mess = " << i << endl;
        system("PAUSE");
        return EXIT_SUCCESS;
}
...
Рейтинг: 0 / 0
31.01.2007, 13:45
    #34296055
Ой Вэй
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание и использование DLL
Ну знаешь ли...

Код: plaintext
func1 Mess;
Ты объявил указатель на функцию, и чему он по твоему равен? Отвечаю — мусору. Надо его инициализировать адресом функции в dll. А для этого ещё неплохо было бы dll загрузить или знать, что она уже загружена.

Посмотри функции LoadLibrary, GetProcAddress.
...
Рейтинг: 0 / 0
31.01.2007, 19:39
    #34297478
Ivan Aleksandrovich
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание и использование DLL
Пока носом не ткнут сам не увижу... видимо уже запарился, ибо глупая ошибка.
Во первых спасибо за ответы.
А во вторых...

Ой ВэйНу знаешь ли...
Код: plaintext
func1 Mess;
Посмотри функции LoadLibrary, GetProcAddress.
Загружать библиотеку через LoadLibrary уже научился чуть ранее. Вот этот код работает:
Код: plaintext
1.
2.
3.
4.
5.
typedef int (APIENTRY *func1)(int i1,int i2);
HINSTANCE hLib=LoadLibrary("libr.dll");
func1 Mess=(int(APIENTRY*)(int i1,int i2))GetProcAddress(hLib,"HelloWorld");
int i=Mess( 5 , 10 );
cout << "i after execute Mess(5,10) : " << i << endl;
FreeLibrary(hLib);

Станислав СНу так нету у тебя функции Mess... И никакой другой функции нет по этому адресу...
Это то же самое, что работать с массивом через указатели...

Добавл соответствующую строчку.

Хотелось бы слинковать используя либы. А вот ошибка все равно остается:
Код: plaintext
  [Linker error] undefined reference to `_imp___Z10HelloWorldii'
Файл libr.lib к проекту подключил, но всеравно undefined reference. Как я понимаю дело в искажении имени функции при компиляции, но разве __declspec не должен это устранить? Или я чего-то не понимаю?
Пробовал также изменить файл libr.h, добавив extern "C":
Код: plaintext
1.
2.
3.
4.
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT extern "C" __declspec (dllimport)
#endif /* Not BUILDING_DLL */
Из имени функции исчезло Z10:
Код: plaintext
  [Linker error] undefined reference to `_imp__HelloWorld'
Но ошибка осталась. Прошу помощи.
...
Рейтинг: 0 / 0
31.01.2007, 20:32
    #34297540
Ivan Aleksandrovich
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание и использование DLL
Выдача tdump:
. . .
******************************************************************************
Section: Exports
Flags: 00000000
Time Stamp: 45C0B4CD : Wed Jan 31 18:25:01 2007
Major Version: 0000
Minor Version: 0000

Exports from libr.dll
1 exported name(s), 1 export addresse(s). Ordinal base is 1.
Not sorted
RVA Ord. Hint Name
-------- ---- ---- ----
000011D0 1 0000 HelloWorld
...
Рейтинг: 0 / 0
01.02.2007, 12:34
    #34298830
Ой Вэй
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание и использование DLL
Давай не путать LoadLibrary/GetProcAddress и
Код: plaintext
слинковать используя либы

В первом случае необходимо объявить функцию в файле def, в разделе EXPORTS — просто написать имя функции:
Код: plaintext
1.
EXPORTS
MyFunc

Тогда её можно будет загрузить по обычному (недекорированному) имени.

Во втором случае ни LoadLibrary, ни GetProcAddress не нужны (не необходимы).
Надо подключить файл *.h с прототипом функции, чтобы отработал транслятор. А потом слинковаться с *.lib, тогда а) линкер распознает функцию; б) при запуске ехе сам подгрузит dll.

Получилось?
...
Рейтинг: 0 / 0
02.02.2007, 13:10
    #34302020
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание и использование DLL
Ivan Aleksandrovich....Прошу помощи. И благодарен за ответы

свои пять копеек...
существует понятие явная и не явная загрузка дэлеле.
Явно - когда Вы сами грузите её и просите - дай-ка мне удресс вот на эту вот хренотень...Имя хренотени должно совпадать с тем именем что экспортирует дэлеле (про дэф файл ужо прозвучало).
НЕ ЯВНО - когда за Вас всю работу берёт О'могущественный компилятор (уж лучше бы он это иногда и не делал!). Т.е. Вам досаточно указать в коде ашничек с описанием той хренотени что Вам нужна (ну например класс) и сказать линковщику - скушайка браток либу, в которой ты надёшь имя дэлеле которую нуна грузить, а так же имя по которому ты там найдёшь хренотень из ашничка....Код загрузки дэлеле и взятие необходимого Вам адреса (и прописывание во все ссылочные места Вашего кода) - будет сделано без Вашего участия, в фоновом режиме...

несколько слов об встречающихся ошибках...
1) Ни фига не пойму, что это за символы, что это за хренотень в коде? Ошибка компилятора...(кусок Вашего кода ничего не знает об Ваших тайных помыслах заюзать некий класс или некую другую хренотень). Необходимо просто подключить ашничек выше того места, где Вы впервые упамянули Вашу хренотень.
2) Не могу найти, после всех компиляций, ответ - где же взять мне эту хренотень с именем "бла-бла-бла" на которую ссылаются в модуле "бла-бла-бла". Ошибка линковщика... (собственно линковщик рад бы Вам помочь, но перерывать все диски-флэшки-локальную сеть ему как то в лом...). Необходимо линковщику дать на вход путя и имя либы, где описана Ваша хренотень.
3) Грузюсь, но чегой-то не хватает. Первое, что не вижу - модуль "бла-бла-бла". Посему - шли бы Вы подальше...(при попытке создать процесс программы и загрузить все модули на которые есть ссылка в бинарнике и дэлелельках - не увенчались успехом. Бинарник - это часть айсберга того хвоста что тащиться вместе с ним. Часто происходит у начинающих программеров, которые предпологают что на всех компах стоит девелопер студия.) Один раз записать аккуратно на листок все модули которые треба и поставлять со своим программным продуктом. Либо дружить с прогой типа дэпендисис и внимать её советам в ввиде ссылок на другие модули...


с уважением
(круглый)
...
Рейтинг: 0 / 0
07.02.2007, 16:05
    #34313145
Ivan Aleksandrovich
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание и использование DLL
Давно не заходил...

авторДавай не путать LoadLibrary/GetProcAddress и
слинковать используя либы
Да я и не путаю.
Говоря "слинковать используя либы" я имел в виду подключение .h и .lib. Разумеется без LoadLibrary и GetProcAddress.
автор
Код: plaintext
#include "libr/dll.h"

Либу тоже подключил. Но линкер все равно обругал:
автор
Код: plaintext
[Linker error] undefined reference to `_imp__HelloWorld'

И вот тут я уже развожу руки.
Специально не поленился, поставил "кривую" MSVC. Он всю эту ерунду собрал без лишней ругани. Поэтому вопрос именно в том, как правильно собирать в DevCpp - mingw.
...
Рейтинг: 0 / 0
09.02.2007, 00:48
    #34317636
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание и использование DLL
Ну где там можно заблудится? Для гнуси библиотека импорта вообще не нужна. Вот, делаем dll на mingw:

1) делаем: add.c
Код: plaintext
1.
2.
int __declspec(dllexport) Addition(int a, int b) {
	return a+b;
}
2) компилируем ее:
gcc -c -o add.o add.c
3) повторяем шаги 1 и 2 для всех модулей
4) собираем dll:
gcc -shared -o arithemtic.dll *.o

Теперь используем ее из C++.
1) Пишем test.cpp
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
#include <iostream>

extern "C" int Addition(int, int);

int main(int argc, char**argv) {
	std::cout << Addition( 3 , 4 );
	return  0 ;
}
2) компилируем
g++ -c -o test.o test.c
3) и собираем exe со статической линковкой на arithemtic.dll:
g++ -o test.exe -d arithemtic.dll test.o
4) Запускаем test.exe - радуемся
5) Удаляем arithemtic.dll - запускаем test.exe, программа падает с ошибкой что не может найти dll. радуемся еще больше.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Создание и использование DLL / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]