Помощь нубу C+

Статус: Offline
Реєстрація: 04.03.2009
Повідом.: 20
Помощь нубу C++

Исходные:
Есть MS Visual Studio.
Есть посторонняя dll-ка.
Необходимо:
Вставить dll в проект и попользовать её функции.
Имена функций известны.
 
Project - > Add Reference - > Browse - указываешь путь к dll
 
Если б так просто.
Необходим пример кода, или ссылка на пример кода в котором подключается dll в проект. В гугле меня не банили, но он даёт ссылки в большей мере на отрывки какието.
 
facepalm-statue1.jpg
 
Project - > Add Reference - > Browse - указываешь путь к dll
+1
а потом вызываеш ту функцию которая у тебя в длл описана
 
Project - > Add Reference - > Browse - указываешь путь к dll
+1
а потом вызываеш ту функцию которая у тебя в длл описана

Давно я уже не писал на C++... описанный способ действительно работает для обычного, unmanaged проекта? И как именно работает? Шо-то я совсем подзабыл, какие есть способы заюзать DLLку более человеческие, чем LoadLibrary/GetProcAddress :confused:
 
Давно я уже не писал на C++... описанный способ действительно работает для обычного, unmanaged проекта? И как именно работает? Шо-то я совсем подзабыл, какие есть способы заюзать DLLку более человеческие, чем LoadLibrary/GetProcAddress :confused:

Собирая исполняемый модуль, который импортирует функции и переменные из DLL, Вы должны сначала создать эту DLL А для этого нужно следующее.

Прежде всего Вы должны подготовить заголовочный файл с прототипами функций, структурами и идентификаторами, экспортируемыми из DLL. Этот файл включается в исходный код всех модулей Вашей DLL. Как Вы потом увидите, этот же файл понадобится и при сборке исполняемого модуля (или модулей), который использует функции и переменные из Вашей DLL
Вы пишете на С/С++ модуль (или модули) исходного кода с телами функций и определениями переменных, которые должны находиться в DLL. Так как эти модули исходного кода не нужны для сборки исполняемого модуля, они могут остаться коммерческой тайной компании-разработчика.
Компилятор преобразует исходный код модулей DLL в OBJ-файлы (по одному на каждый модуль).
Компоновщик собирает все OBJ-модули в единый загрузочный DLL-модуль, в который в конечном итоге помещаются двоичный код и переменные (глобальные и статические), относящиеся к данной DLL Этот файл потребуется при компиляции исполняемого модуля
Если компоновщик обнаружит, что DLL экспортирует хотя бы одну переменную или функцию, то создаст и LIB-файл Этот файл совсем крошечный, поскольку в нем нет ничего, кроме еписка символьных имен функций и переменных, экспортируемых из DLL Этот LIB-файл тоже понадобится при компиляции ЕХЕ-файла.
Создав DLL, можно перейти к сборке исполняемого модуля.
Во все модули исходного кода, где есть ссылки на внешние функции, переменные, структуры данных или идентификаторы, надо включить заголовочный файл, предоставленный разработчиком DLL.

Вы пишете на С/С++ модуль (или модули) исходного кода с телами функций и определениями переменных, которые должны находиться в ЕХЕ-файле. Естественно, ничто не мешает Вам ссылаться на функции и псрсмснные, определенные в заголовочном файле DLL-модуля
Компилятор преобразует исходный код модулей EXE в OBJ-файлы (по одному на каждый модуль).
Компоновщик собирает все OBJ-модули в единый загрузочный ЕХЕ-модуль, в который в конечном итоге помещаются двоичный код и переменные (глобальные и статические), относящиеся к данному EXE. В нем также создается раздел импорта, где перечисляются имена всех необходимых DLL-модулей (информацию о разделах см в главе 17) Кроме того, для каждой DLL в этом разделе указывается, па какие символьные имена функций и переменных ссылается двоичный код исполняемого файла. Эти сведения потребуются загрузчику операционной системы, а как именно он ими пользуется — мы узнаем чуть позже.
Создав DLL- и ЕХЕ-модули, приложение можно запустить. При его запуске загрузчик операционной системы выполняет следующие операции

Загрузчик операционной системы создает виртуальное адресное пространство для нового процесса и проецирует па пего исполняемый модуль.
Далее загрузчик анализирует раздел импорта, находит все необходимые DLLмодули и тоже проецирует на адресное пространство процесса. Заметьте, что DLL может импортировать функции и переменные их другой DLL, а значит, у нее может быть собственный раздел импорта. Заканчивая подготовку процесса к работе, загрузчик просматривает раздел импорта каждого модуля и проецирует все требуемые DLL-модули на адресное пространство этого процесса. Как видите, на инициализацию процесса может уйти довольно длительное время.
(c) Джеффри Рихтер "Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows"
 
Если б так просто.
Необходим пример кода, или ссылка на пример кода в котором подключается dll в проект. В гугле меня не банили, но он даёт ссылки в большей мере на отрывки какието.

Тільки зареєстровані користувачі бачать весь контент у цьому розділі
, сорри не досмотрел что С++
 
Компоновщик собирает все OBJ-модули в единый загрузочный ЕХЕ-модуль, в который в конечном итоге помещаются двоичный код и переменные (глобальные и статические), относящиеся к данному EXE. В нем также создается раздел импорта, где перечисляются имена всех необходимых DLL-модулей (информацию о разделах см в главе 17) Кроме того, для каждой DLL в этом разделе указывается, па какие символьные имена функций и переменных ссылается двоичный код исполняемого файла.

ASokol: Спасибо, теорию-то то я знаю и Рихтера в свое время читал от корки до корки. Только для того, чтобы получилось процитированное, компоновщику надо "скормить" .LIB файл для используемой DLL, а его, насколько я понял условия задачи, как раз и нет. Я, собственно, поэтому и удивился - неужели новая Visual Studio .LIB сама файлы умеет генерировать динамически по данной DLLке? Или я "отстал от жизни" и в новой Visual Studio добавили какой-то еще способ указать, из какой DLL импортируется та или иная функция?
 
Ну если нет lib-файла, то LoadLibrary/GetProcAddress. :)
 
Вот:

Процесс создания и использования библиотек DLL.

Процесс создания динамической библиотеки проходит в два этапа. Первый из них заключается в создании файла-заголовка (*.h), который определяет основные свойства проекта.
С помощью "визарда" среды Microsoft Visual C++ создайте новый проект, выбрав в качестве типа проекта Dinamic Linked Library , после чего определите "пустой проект" (empty project). Теперь вам предстоит самостоятельно создать файлы проекта. Пусть имя вашего проекта будет funlib.
Создайте файл заголовка – funlib.h (при помощи меню File\New..., выбрав файл-заголовок ). В этом файле наьерите следующий текст:

/
Код:
/ File funlib.h

#define EXPORT extern "C" __declspec(dllexport)

EXPORT BOOL CALLBACK return333();
EXPORT int CALLBACK MyInc(int i);

Первая строка файла определяет некоторую директиву EXPORT, которая будет использоваться для подключения сервисов, необходимых для создания ссылок на экспортируемые функции (то есть функции, которые могут быть использованы или импортированы другими программами). Следующие две строки являются предварительным объявлением функций, директива EXPORT и делает их динамическими функциями.
Теперь осталось написать обычный текст программы *.cpp, который мало чем отличается от обычного:

Код:
//funlib.cpp

#include <windows.h>
#include <string.h>
#include "fulib.h"

int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
           return TRUE;
}

EXPORT BOOL CALLBACK EdrCenterText()
{
	return 333;
}

EXPORT int CALLBACK MyInc(int i)
{
	return ++i;
}

Незнакомой здесь является только функция DllMain, которая является аналогом функции main для консольных приложений и функции WinMain для приложений, написанный под Windows. Эта функция автоматически вызывается при загрузке любой dll. Возвращаемое значение TRUE свидетельствует об успешной загрузке и инициализации внутренних ресурсов. Остальные две функции являются обычными функциями пользователя, а директива EXPORT уже нам знакома. Все. Компилируем проект и dll готова!
Настала пора ее использования. Для этого создадим обычное консольное приложение Win32 и назовем его usedll. Для использования funlib.dll необходимо выполнить следующие: поместить в каталог проекта файлы funlib.h и funlib.lib. Второй файл является результатом компиляции предыдущего проекта и его можно найти в каталоге Debug. Кроме этого, в меню Project\Settings\Link, Категория General, поле Object\library modules необходимо вписать имя файла-библиотеки для организации настроек связывания. Текст программы usedll.cpp приведен ниже.

Код:
// usedll.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include "iostream.h"
#include "funlib.h"

int main(int argc, char* argv[])
{
	cout<<return333()<<endl;
	cout<<MyInc(5)<<endl;
	return 0;
}

Данная программа выполнится если в каталоге, где располагается файл usedll.exe расположен файл динамической библиотеки funlib.dll. В результате выполнения данной программы на экране вы увидите следующую картину:
333
6
В заключении следует отметить, что используя механизмы динамического связывания, можно определять не только функции, но переменные и даже классы.

Второй способ использования DLL
Рассмотренный выше способ написания программы, использующей динамически подключаемые библиотеки пригоден только в том случае, когда вы сами создали библиотеки, или, по крайней мере, вы имеете в наличии файл библиотеки *.lib. Однако, очень часто случается так, что есть только *.dll (или она только планируется). В этом случае можно использовать другой способ, который не требует для компиляции проекта наличия файлов, связанных с вызываемой *.dll.
Применение данного способа заключается в следующем:
1. Создаются прототипы функций, имеющие те же параметры, что и необходимые функции внутри *.dll. Для нашего примера это будет выглядеть так:
typedef BOOL (WINAPI * Inc)(int i);
2. Объявляется переменная типа указателя на данную функцию:
Inc pI;
3. В программе осуществляется загрузка библиотеки:
HINSTANCE hL;
hL=LoadLibrary("funlib.dll");
4. объявленному указателю на функцию присваивается адрес функции из *.dll:
pI=(Inc)GetProcAddress(hL,(LPCSTR)2);
5. Функция используется по назначению:
cout<<pI(6);
6. После использования выгружается из памяти:
FreeLibrary(hL);
Целиком рассмотренный пример выглядит следующим образом:

Код:
#include "stdafx.h"
#include "iostream.h"
#include "windows.h"

HINSTANCE hL;
typedef int (CALLBACK * Inc)(int i);
Inc pI;

int main(int argc, char* argv[])
{   hL=LoadLibrary("1111.dll");
    pI=(Inc)GetProcAddress(hL,(LPCSTR)2);
    cout<<pI(6);
	FreeLibrary(hL);
	return 0;
}

Наличие *.dll требуется только во время запуска *.exe файла.
 
кроме имен функций,нужно также знать используемую конвенцию вызовов, а также типы и порядок следования всех аргументов для каждой из функций...
 
Спасибо всем кто отписался. LoadLibrary и GetProcAddress сделали всё что нужно. Немного ввели в ступор ошибки связанные с calling conventions. Литературу изучил и вродь разобрался.
 
Назад
Зверху Знизу