Работа с Dll. Как?
Хочу занести пару функций в DLL, но не знаю как эта самая DLL пишется. Нашел пару примеров, но прога вылетает из-за недопустимой операции. Просьба: пришлите пример хотя-бы самой простой DLL'ки с одной экспортируемой функцией, а также необходим кусок кода основной программы, который подключал бы функции из библиотеки. [mmr@km.ru]
Здрассте, приехали. Там даже мастер по созданию DLL пример экспортирования. А чтобы вызывать включаешь header и вызваешь ее как обычно.
Здрассте, приехали. Там даже мастер по созданию DLL пример экспортирования. А чтобы вызывать включаешь header и вызваешь ее как обычно.
Включая header, получим статически подключенную библиотеку. А я хочу подключить ее динамически, функцией LoadLibrary. Только вот прога вылетает. Потому и прошу небольшой, но рабочий исходник.
Включая header, получим статически подключенную библиотеку. А я хочу подключить ее динамически, функцией LoadLibrary. Только вот прога вылетает. Потому и прошу небольшой, но рабочий исходник.
Это называется не статически, ну да ладно.
Вопросы:
1)как делаешь?
2)где выдает ошибку?
3)объявил ли в .def файле или не знал об этом
Это называется не статически, ну да ладно.
Вопросы:
1)как делаешь?
2)где выдает ошибку?
3)объявил ли в .def файле или не знал об этом
Ну помимо .def файла еще можно использовать __declspec(dllexport).
Если коротко:
Чтобы тебе сделать ДЛЛ - необходимо:
1. Обязательно объявить DllMain - причем вернуть на выходе из нее верное значение - (кажется TRUE) - ежели память не изменяет.
2. Корректно написать функции и экспортировать их либо через .def файл (ИМХО в ряде случаев удобнее), либо через __declspec(dllexport) - что проще, если не хочешь возиться с .DEF файлом.
Вот собсно и все.
#define EXPORT extern "C" __declspec (dllexport)
EXPORT int CALLBACK SomeFunc(char *str);
int WINAPI DllMain(HINSTANCE hInstance, DWORD fdReason, PVOID pvReserved)
{ return 1;
}
EXPORT int CALLBACK SomeFunc(char *str)
{ MessageBox(NULL, str, "From DLL", MB_OK);
return 1;
}
Все это без ошибок компилируется в файл Dll_C.dll. Теперь текст самой проги:
typedef int (WINAPI *PFN_MyFunction)(char *);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{ HINSTANCE hMyDll;
if((hMyDll = LoadLibrary("Dll_C")) == NULL) return 1;
PFN_MyFunction pfnFunc;
int iCode;
pfnFunc = (PFN_MyFunction)GetProcAddress(hMyDll, "SomeFunc");
iCode = (*pfnFunc)("Hello");
FreeLibrary(hMyDll);
return 0;
}
Компиляция проходит опять без ошибок, но при запуске - недопустимая операция. Сама библиотека и исполняемый файл лежат в одной папке.
В тексте самой библиотеки пишу это:
#define EXPORT extern "C" __declspec (dllexport)
EXPORT int CALLBACK SomeFunc(char *str);
int WINAPI DllMain(HINSTANCE hInstance, DWORD fdReason, PVOID pvReserved)
{ return 1;
}
EXPORT int CALLBACK SomeFunc(char *str)
{ MessageBox(NULL, str, "From DLL", MB_OK);
return 1;
}
Все это без ошибок компилируется в файл Dll_C.dll. Теперь текст самой проги:
typedef int (WINAPI *PFN_MyFunction)(char *);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{ HINSTANCE hMyDll;
if((hMyDll = LoadLibrary("Dll_C")) == NULL) return 1;
PFN_MyFunction pfnFunc;
int iCode;
pfnFunc = (PFN_MyFunction)GetProcAddress(hMyDll, "SomeFunc");
iCode = (*pfnFunc)("Hello");
FreeLibrary(hMyDll);
return 0;
}
Компиляция проходит опять без ошибок, но при запуске - недопустимая операция. Сама библиотека и исполняемый файл лежат в одной папке.
Напиши def файл
#define EXPORT extern "C" __declspec (dllexport)
EXPORT int SomeFunc(char *str); // без CALLBACK
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdReason, PVOID pvReserved) // Правильнее BOOL, хотя это не критично
{
return TRUE; // Тоже не критично
}
EXPORT int SomeFunc(char *str) // без CALLBACK
{
MessageBox(NULL, str, "From DLL", MB_OK);
return 1;
}
typedef int (*PFN_MyFunction)(char *); // здесь без WINAPI
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
HINSTANCE hMyDll = LoadLibrary("Dll_C");
if(!hMyDll) return 1;
PFN_MyFunction pfnFunc = (PFN_MyFunction)GetProcAddress(hMyDll, "SomeFunc");
int iCode = pfnFunc("Hello"); // Здесь не надо явно разыменовывать указатель
FreeLibrary(hMyDll);
return 0;
}
Для pavor:
Ну и зачем здесь def-файл?
Я кое-что подправил, посмотри:
#define EXPORT extern "C" __declspec (dllexport)
EXPORT int SomeFunc(char *str); // без CALLBACK
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdReason, PVOID pvReserved) // Правильнее BOOL, хотя это не критично
{
return TRUE; // Тоже не критично
}
EXPORT int SomeFunc(char *str) // без CALLBACK
{
MessageBox(NULL, str, "From DLL", MB_OK);
return 1;
}
typedef int (*PFN_MyFunction)(char *); // здесь без WINAPI
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
HINSTANCE hMyDll = LoadLibrary("Dll_C");
if(!hMyDll) return 1;
PFN_MyFunction pfnFunc = (PFN_MyFunction)GetProcAddress(hMyDll, "SomeFunc");
int iCode = pfnFunc("Hello"); // Здесь не надо явно разыменовывать указатель
FreeLibrary(hMyDll);
return 0;
}
Для pavor:
Ну и зачем здесь def-файл?
CALLBACK и WINAPI = __stdcall
CALLBACK и WINAPI = __stdcall
Кто тебе такую глупость сказал?
Ты не задумывался, почему бы тогда не писать просто __stdcall ?
Это макрос и раскрываться он может в зависимости от параметров компиляции.
Читаем MSDN:
CALLBACK Calling convention for callback functions.
WINAPI Calling convention for system functions.
К предыдущему посту:
так зачем тебе понадобился .def ?
Кто тебе такую глупость сказал?
Ты не задумывался, почему бы тогда не писать просто __stdcall ?
Это макрос и раскрываться он может в зависимости от параметров компиляции.
Читаем MSDN:
К предыдущему посту:
так зачем тебе понадобился .def ?
Просто делал все время через .def и не заморачивался. Поэтому не могу посоветовать насчет __declspec(dllexport).
Поправки BioUnit'а принесли свои плоды. Все работает. Скорее всего, не надо было разыменовывать указатель при вызове функции из библиотеки, в этом и была ошибка.
В догонку. Бывает много проблем с именами функций в dll - вредит декорирование имён. Например, функция __stdcall f(int, int) в конце концов будет называться _f@8, а если не напишешь extern "C", то имена бубут ещё страшнее. Чтобы этого не происходило, можно не писать в тексте программы директив __declspec(dllexport), но написать .def-файл - тогда декорирования не будет.
В догонку. Бывает много проблем с именами функций в dll - вредит декорирование имён. Например, функция __stdcall f(int, int) в конце концов будет называться _f@8, а если не напишешь extern "C", то имена бубут ещё страшнее. Чтобы этого не происходило, можно не писать в тексте программы директив __declspec(dllexport), но написать .def-файл - тогда декорирования не будет.
отож8)
Я кое-что подправил, посмотри:
#define EXPORT extern "C" __declspec (dllexport)
EXPORT int SomeFunc(char *str); // без CALLBACK
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdReason, PVOID pvReserved) // Правильнее BOOL, хотя это не критично
{
return TRUE; // Тоже не критично
}
EXPORT int SomeFunc(char *str) // без CALLBACK
{
MessageBox(NULL, str, "From DLL", MB_OK);
return 1;
}
typedef int (*PFN_MyFunction)(char *); // здесь без WINAPI
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
HINSTANCE hMyDll = LoadLibrary("Dll_C");
if(!hMyDll) return 1;
PFN_MyFunction pfnFunc = (PFN_MyFunction)GetProcAddress(hMyDll, "SomeFunc");
int iCode = pfnFunc("Hello"); // Здесь не надо явно разыменовывать указатель
FreeLibrary(hMyDll);
return 0;
}
Я пробовал компилить пример - dll OK, а программа, что dll подключает:
Compiling...
StdAfx.cpp
Compiling...
dll_load2.cpp
Linking...
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/dll_load2.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
dll_load2.exe - 2 error(s), 0 warning(s)
З.Ы. VC++ 6
Green
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
[/CODE]
Если ты создаешь консольное приложение, то в коде должна быть функция main, если ты создаешь оконное приложение, то - WinMain.
Если ты создаешь консольное приложение, то в коде должна быть функция main, если ты создаешь оконное приложение, то - WinMain.
Заменил WinMain на main (у меня консоль), все компилируется, но Длл не грузится:( .
Это моя первая попытка создать такого рода приложение, поэтому возможно что-то перепутал. К примеру, "Dll_C" это общий стандарт или имя dll-файла (dll.dll получаетмся в таком случае:-?)