Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.64
KatyPet
4 / 4 / 1
Регистрация: 26.10.2012
Сообщений: 16
#1

Как подключить пользовательскую DLL к приложению - C++

26.10.2012, 00:33. Просмотров 2033. Ответов 29
Метки нет (Все метки)

Добрый вечер! Я первый раз пишу dll. Вот ее текст:
My.cpp:
C++
1
2
3
4
5
6
7
#include<iostream>
#include "My.h"
using namespace std;
namespace myspace
{
    void MyClass::hw(void) {cout<<"HelloWorld";}
}
И My.h:
C++
1
2
3
4
5
6
7
8
namespace myspace
{
    class MyClass
    {
    public:
        static __declspec(dllexport) void hw(void);
    };
}
Компилирую в Visual Studio, всё нормально.
А теперь пытаюсь написать программу, которая будет использовать эту dll. Вот здесь проблема. Вот текст этой программы:
UsesDll.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include "stdafx.h"
#include "My.h"
#include<iostream>
#include<conio.h>
#pragma comment(lib, "?.lib")
int main()
{
    myspace::MyClass::hw();
    std::cout<<"Dll used\n";
    getch();
    return 0;
}
My.h:
C++
1
2
3
4
5
6
7
8
namespace myspace
{
    class MyClass
    {
    public:
        static __declspec(dllexport) void hw(void);
    };
}
И там еще stafx.h, stdafx.cpp и targetver.h, которые Visual Studio добавило само.
Так вот, эта программа не линкуется - появляется ошибка:
error LNK2019: unresolved external symbol "public: static void __cdecl myspace::MyClass::hw(void)" (?hw@MyClass@myspace@@SAXZZ) referenced in function _main.
Что посоветуете?

Добавлено через 19 минут
Точнее, в пятой строке файла UsesDll.cpp нет никакого pragma и так далее.
http://www.cyberforum.ru/cpp-beginners/thread1500978.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.10.2012, 00:33
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Как подключить пользовательскую DLL к приложению (C++):

Как подключить DLL
Доброе время суток уважаемые участники Пытаюсь написать программу по...

Как подключить в С++ dll-ку из C#?
Создал в Visual Studio dll-ку на C#. Хочу подключить ее в С++, не выходит. ...

Как подключить dll к проекту?
Ребят помогите пожалуйста, если сможете а то я уже 3 дня долбаюсь чет никак не...

Как подключить библиотеку i7000.dll?
у меня есть библиотека i7000.dll библиотека необходимая для работы с com...

как подключить dll и lib SDL
как подключить к проекту(в Visual Studio 2010) библиотеку SDL?// есть SDL.dll,...

29
Kastaneda
Jesus loves me
Эксперт С++
4759 / 2962 / 340
Регистрация: 12.12.2009
Сообщений: 7,520
Записей в блоге: 2
Завершенные тесты: 1
26.10.2012, 09:11 #2
Посмотри, может поможет.
1
KatyPet
4 / 4 / 1
Регистрация: 26.10.2012
Сообщений: 16
26.10.2012, 11:04  [ТС] #3
Посмотрела тему по ссылке. Теперь код моей программы, использующей DLL, выглядит так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef void (*hw)(void);
#include "stdafx.h"
#include "My.h"
#include<iostream>
#include<conio.h>
int main()
{
    HMODULE hLib=LoadLibrary(LPCWSTR("MyDll.dll"));
    hw func=(hw)GetProcAddress(hLib, "hw");
    func();
    std::cout<<"Dll used\n";
    getch();
    return 0;
}
Теперь программа компилируется и линкуется нормально, но не работает. Она останавливается на месте вызова func() и говорит "Unhandled exception at 0x00000000 in UsesDll.exe: 0xC0000005: Access violation".
0
Kastaneda
Jesus loves me
Эксперт С++
4759 / 2962 / 340
Регистрация: 12.12.2009
Сообщений: 7,520
Записей в блоге: 2
Завершенные тесты: 1
26.10.2012, 11:08 #4
Код DLL тоже поменяй.

Добавлено через 1 минуту
C++
1
2
3
4
5
BOOL _stdcall DllMain(HINSTANCE hInst, DWORD Reason, LPVOID reserved){
  if(Reason==DLL_PROCESS_ATTACH)
       hInstance = hInst;
       return true;
}
DllMain обязательная функция.
0
KatyPet
4 / 4 / 1
Регистрация: 26.10.2012
Сообщений: 16
26.10.2012, 17:54  [ТС] #5
Поменяла код dll. Теперь он такой: MyDll.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
#include "My.h"
#include<windows.h>
using namespace std;
HINSTANCE hInstance=NULL;
namespace myspace
{
    BOOL _stdcall DllMain(HINSTANCE hInst, DWORD Reason, LPVOID reserved)
    {
       if(Reason==DLL_PROCESS_ATTACH)
       {
          hInstance = hInst;
          return true;
        }
    }
    void MyClass::hw(void) {cout<<"HelloWorld";}
}
А все равно при запуске та же ошибка.
Я думаю, проблема не в DLL, а в программе, использующей DLL. Потому что я попробовала ее запустить, не подкладывая DLL рядом с ней в папку, и, вместо того, чтоб вывести сообщение, что требуется такая-то DLL (как это делают нормальные программы), она выдает все ту же ошибку.
0
Игорь с++
472 / 464 / 63
Регистрация: 26.01.2011
Сообщений: 2,033
26.10.2012, 22:26 #6
есть два метода загрузки dll статитческий и динамический если загружать статически и не класть dll рядом то будет то сообщение о котором ты писала , а вот если динамически и не положить dll , то бог знает , что может произойти , может и вообще не чего , а может и программа провалиться с грохотом, ты уж определись как ты хочеш её загрузить !
0
Croessmah
++Ͻ
14147 / 8072 / 1512
Регистрация: 27.09.2012
Сообщений: 19,910
Записей в блоге: 3
Завершенные тесты: 1
26.10.2012, 22:30 #7
Цитата Сообщение от Игорь с++ Посмотреть сообщение
есть два метода загрузки dll статитческий и динамический если загружать статически и не класть dll рядом то будет то сообщение о котором ты писала , а вот если динамически и не положить dll , то бог знает , что может произойти , может и вообще не чего , а может и программа провалиться с грохотом, ты уж определись как ты хочеш её загрузить !
Само название DLL дает понять, что это должна быть динамическая библиотека
0
ValeryS
Модератор
7124 / 5392 / 669
Регистрация: 14.02.2011
Сообщений: 18,210
26.10.2012, 22:35 #8
Цитата Сообщение от Игорь с++ Посмотреть сообщение
динамический
это LoadLibrary и тогда нужно не класть рядом а прописать путь к dl
если путь не прописать то будет искать в своей папке папке видос и как там пути настроены
и конечно проверять что возвращает функция
C++
1
2
if(!(dasWordl_dll=LoadLibrary("имя библиотеки")))
        return false;// ошибка загрузки делать нечего
Цитата Сообщение от Игорь с++ Посмотреть сообщение
статически и не класть dll рядом
а вот это на этапе компиляции и нужна не Dll а lib, которая так же компилируется при создании Dll
но если в настройках компилятора стоит линковать динамически то Dll тоже нужна и рядом с программой или в системных папках
0
Игорь с++
472 / 464 / 63
Регистрация: 26.01.2011
Сообщений: 2,033
26.10.2012, 22:58 #9
Цитата Сообщение от Croessmah Посмотреть сообщение
Само название DLL дает понять, что это должна быть динамическая библиотека
название может и даёт понятие , но способа загрузки два !

Цитата Сообщение от ValeryS Посмотреть сообщение
это LoadLibrary и тогда нужно не класть рядом а прописать путь к dl
если путь не прописать то будет искать в своей папке папке видос и как там пути настроены
во первых согласен , что не обязательно , но с другой стороны если не прописать путь и не положить либо рядом либо в системную папку ОС , то интересно посмотреть , что из этого у тебя получится ?
Цитата Сообщение от ValeryS Посмотреть сообщение
а вот это на этапе компиляции и нужна не Dll а lib, которая так же компилируется при создании Dll
я про это и говорил , но нужна она только на этапе компиляции , да и ещё даже если ты и линкуеш статически , то даже и в этом случае не обязательно держать dll в своей папке , её так же можно бросить в системную папку ОС.
0
ValeryS
26.10.2012, 22:59
  #10

Не по теме:

Цитата Сообщение от Игорь с++ Посмотреть сообщение
то интересно посмотреть , что из этого у тебя получится ?
а ничего не получится
правда узнаешь ты об этом на этапе исполнения, компилятор слова не скажет
для этого и нужна проверка

0
Игорь с++
472 / 464 / 63
Регистрация: 26.01.2011
Сообщений: 2,033
26.10.2012, 23:01 #11
Цитата Сообщение от ValeryS Посмотреть сообщение
а ничего не получится
для этого и нужна проверка
согласен , но может и прога провалиться
0
ValeryS
Модератор
7124 / 5392 / 669
Регистрация: 14.02.2011
Сообщений: 18,210
26.10.2012, 23:04 #12
Цитата Сообщение от Игорь с++ Посмотреть сообщение
то даже и в этом случае не обязательно держать dll в своей папке , её так же можно бросить в системную папку ОС.
ну а я про что
Цитата Сообщение от ValeryS Посмотреть сообщение
то Dll тоже нужна и рядом с программой или в системных папках
пардон опечатка
читать так
Цитата Сообщение от ValeryS Посмотреть сообщение
то Dll тоже нужна или рядом с программой или в системных папках
Добавлено через 2 минуты
Цитата Сообщение от Игорь с++ Посмотреть сообщение
согласен , но может и прога провалиться
перечитай сообщение я добавил
Цитата Сообщение от ValeryS Посмотреть сообщение
правда узнаешь ты об этом на этапе исполнения, компилятор слова не скажет
а для того чтобы не валилась после проверки или экстренный выход или пиши сообщение пользователю "не могу найти"
0
Игорь с++
472 / 464 / 63
Регистрация: 26.01.2011
Сообщений: 2,033
26.10.2012, 23:05 #13
мы с тобой пробуем объснить друг другу , что и так сами понимаем , а вот ТС когда почитает всё это наверно будет в таком состаянии -
1
KatyPet
4 / 4 / 1
Регистрация: 26.10.2012
Сообщений: 16
27.10.2012, 14:06  [ТС] #14
Из всего, что вы написали, я поняла, что хочу сделать динамический метод загрузки. Использую LoadLibrary в коде программы. Не прописываю путь к DLL, но кладу ее в папку рядом с программой. И все равно, при текстах программы и DLL, которые я выложила ранее, программа ломается в момент вызова func. В чем проблема?
0
ValeryS
Модератор
7124 / 5392 / 669
Регистрация: 14.02.2011
Сообщений: 18,210
27.10.2012, 14:24 #15
Я тебе приведу кусок моей проги как работать с dll
C++
1
2
3
4
5
6
7
8
9
10
// объявить глобально чтобы все видели
int( __cdecl*DasWordInit)(char); //указатель на функцию описывается её прототип и соглашение по вызову
 HMODULE dasWordl_dll; // хандлер библиотеки
int init_DasWord()
{
 
    if(!(dasWordl_dll=LoadLibrary(_T("Dasword.dll")))) // загружаем библиотеку
        return 0; // если не загрузилась делать нечего выходим,можно чтото написать пользователю
  if(!((FARPROC &)DasWordInit=GetProcAddress(dasWordl_dll, "DasWordInit")))// загружаем функцию
        return 0;// если не загрузилась делать нечего выходим
и только потом можно вызвать функцию
C++
1
DasWordInit(0);
соглашение по вызову __cdec есть еще __stdcall (на самом деле их больше это самые главные)от этого зависит кто чистит стек и как передаются параметры (прочитай про них обязательно неправильное условие роняет программу)
http://msdn.microsoft.com/ru-ru/library/zkwh89ks.aspx
http://msdn.microsoft.com/ru-ru/library/zxk0tw93.aspx
1
Игорь с++
472 / 464 / 63
Регистрация: 26.01.2011
Сообщений: 2,033
27.10.2012, 20:19 #16
Вот смотри накидал простенькую dll которая просто выводит надпись в окне , и программу которая загружает эту dll делает все необходимые проверки и если всё нормально , то использует функцию из dll.
0
Вложения
Тип файла: rar Project1.rar (323.9 Кб, 15 просмотров)
KatyPet
4 / 4 / 1
Регистрация: 26.10.2012
Сообщений: 16
27.10.2012, 21:37  [ТС] #17
Попробовала применить совет ValeryS. Теперь DLL выглядит так:
My.h:
C++
1
2
3
4
5
class MyClass
{
public:
    static __declspec(dllexport) void hw(void);
};
MyDll.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include "My.h"
#include<windows.h>
using namespace std;
HINSTANCE hInstance=NULL;
void MyClass::hw(void) {cout<<"HelloWorld";}
bool _stdcall DllMain(HINSTANCE hInst, DWORD Reason, LPVOID reserved)
{
    if(Reason==DLL_PROCESS_ATTACH)
    {
        hInstance=hInst;
        return true;
    }
}
,
Программа, использующая DLL:
My.h такое же, а UsesDll.cpp:
C++
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
#include "stdafx.h"
#include "My.h"
#include<iostream>
#include<conio.h>
#include<windows.h>
void ( __cdecl *hw)(void);
HMODULE hLib;
int main()
{
    if(!(hLib=LoadLibrary(_T("MyDll.dll"))))
    {
        std::cout<<"LoadLibrary doesn't work\n";
        getch();
        return 0;
    }
    if(!((FARPROC &)hw=GetProcAddress(hLib, "hw")))
    {
        std::cout<<"GetProcAddress doesn't work\n";
        getch();
        return 0;
    }
    hw();
    std::cout<<"Dll used\n";
    getch();
    return 0;
}
LoadLibrary уже работает.
Выдает, что не работает GetProcAddress.


Попробовала скомпилировать проект, который прислал Игорь. Почему-то появляется ошибка при компиляции error C2491: 'MyFunc' : definition of dllimport function not allowed, это в dllmain.cpp.
0
Игорь с++
472 / 464 / 63
Регистрация: 26.01.2011
Сообщений: 2,033
27.10.2012, 21:49 #18
Цитата Сообщение от KatyPet Посмотреть сообщение
Почему-то появляется ошибка при компиляции
а портатип записала в dll.h и подключила к dllmain ?
1
Kastaneda
Jesus loves me
Эксперт С++
4759 / 2962 / 340
Регистрация: 12.12.2009
Сообщений: 7,520
Записей в блоге: 2
Завершенные тесты: 1
27.10.2012, 21:57 #19
тыц
1
ValeryS
Модератор
7124 / 5392 / 669
Регистрация: 14.02.2011
Сообщений: 18,210
27.10.2012, 22:33 #20
Цитата Сообщение от KatyPet Посмотреть сообщение
Выдает, что не работает GetProcAddress.
открой свою длл в редакторе например PE Explorer и посмотри как выглядит твоя функция
сдается мне что ты не сделала условие "в стиле С" при написании Dll (по крайней мере я не заметил) и название твоей функции исказилось по плюсовым правилам
и она уже называется не hw а по другому

Добавлено через 6 минут
Вот это условие у Игорь с++,
C++
1
2
3
4
#ifdef __cplusplus
extern "C"
{
#endif
добавь это условие в My.h:
хотя твоя функция это метод класса и честно говоря я не знаю куда впихнуть extern "C"
попробуй сначала написать простую функцию типа
C++
1
extern "C" __declspec(dllexport) void hw(void);
и побаловаться с ней

Добавлено через 9 минут
а вообще порекомендую тебе книгу
Дж Рихтер К Назар "Windows via C/C++ программирование на языке Visual C++" Питер 2009
глава 19 Dll основы
глава 20 Dll более сложные методы программирования
по моему очень подробно и понятно написано
1
27.10.2012, 22:33
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.10.2012, 22:33
Привет! Вот еще темы с решениями:

Не удается подключить к приложению gtest и свою статическую либу VS 2010
Здравствуйте, господа. Возникла проблема с линкером в VS 2010 после подключения...

Приложению не удалось запуститься, поскольку MSVCR90D.dll не был найден
Приложению не удалось запуститься, поскольку MSVCR90D.dll не был найден. ...

Как создать файл DLL так, чтобы его можно было подключить к VBA Excel?
Пытаясь научиться подключать к VBA хотя бы самую тривиальную функцию на C++. ...

Подключить dll
Здравствуйте. Есть dll, в ней несколько функций, необходимо добавить еще одну,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru