There is a main program:
#define BUILD_DLL #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <windows.h> #include <ctype.h> #include <string.h> // Структура листа struct listlight { char MD5[33]; // MD5 struct listlight* right; // Правый ребенок }; // Структура листа struct list { struct listlight* first; }; // Глобальные переменные char tmp[33]; HINSTANCE dllp; //Генератор рандомных md5 сумм void RadndomMD5(){ unsigned char i, j; srand(time(NULL)); for (i = 0; i < 32; i++) { j = (rand()%(17)); if (j == 0) tmp[i] = '0'; else if (j == 1) tmp[i] = '1'; else if (j == 2) tmp[i] = '2'; else if (j == 3) tmp[i] = '3'; else if (j == 4) tmp[i] = '4'; else if (j == 5) tmp[i] = '5'; else if (j == 6) tmp[i] = '6'; else if (j == 7) tmp[i] = '7'; else if (j == 8) tmp[i] = '8'; else if (j == 9) tmp[i] = '9'; else if (j == 10) tmp[i] = 'A'; else if (j == 11) tmp[i] = 'B'; else if (j == 12) tmp[i] = 'C'; else if (j == 13) tmp[i] = 'D'; else if (j == 14) tmp[i] = 'E'; else if (j == 15) tmp[i] = 'F'; else i = 0; } } bool slm(const char *str1, const char *str2){ return (strcmp(str1, str2) == 0); } void PrintHelp(){ system("cls"); printf("Справка:\n\n"); printf("Строение: \n|основная комманда|дополнительный параметр|ключ|\n"); printf("\nОсновные комманды: \n"); printf("|ADD |First/End |MD5| - добавление элемента\n"); printf("|REMOVE|First/End/VAL|MD5|true/false| - удаление элемента (true - всех элементов)\n"); printf("|CHECK | | | | - проверка на пустоту\n"); printf("|FIND | |MD5| | - происк элемента\n"); printf("|PRINT | | | | - вывод листа\n"); printf("|CLEAN | | | | - очистка листа\n"); printf("|EXIT | | | | - выход из программы\n"); } void FindFind(struct list* List){ char tmpword[33]; unsigned char i; bool (__stdcall *List_FindMe)(char MD5[32], struct list* List); scanf("%s", tmpword); for (i = 0; i < 33; i++) tmpword[i] = toupper(tmpword[i]); if (dllp) { List_FindMe = (bool(__stdcall *) (char MD5[32], struct list* List)) GetProcAddress(dllp, "_List_FindMe"); } if (slm(tmpword, "RANDOM")){ RadndomMD5(); if (List_FindMe(tmp, List)) printf("true\n"); else printf("false\n"); } else { if (List_FindMe(tmpword, List)) printf("true\n"); else printf("false\n"); } } void AddAdd(struct list* List){ char tmpword[33]; char tmppos[33]; unsigned char i; void (__stdcall *List_Add_First)(char MD5[32], struct list* List); void (__stdcall *List_Add_End) (char MD5[32], struct list* List); if (dllp) { List_Add_First = (void(__stdcall *) (char MD5[32], struct list* List)) GetProcAddress(dllp, "_List_Add_First"); List_Add_End = (void(__stdcall *) (char MD5[32], struct list* List)) GetProcAddress(dllp, "_List_Add_End"); } scanf("%s%s", tmppos, tmpword); for (i = 0; i < 33; i++){ tmpword[i] = toupper(tmpword[i]); tmppos[i] = toupper(tmppos[i]); } if (slm(tmppos, "FIRST")) { if (slm(tmpword, "RANDOM")){ RadndomMD5(); List_Add_First(tmp, List); } else { List_Add_First(tmpword, List); } } else if (slm(tmppos, "END")) { if (slm(tmpword, "RANDOM")){ RadndomMD5(); List_Add_End(tmp, List); } else { List_Add_End(tmpword, List); } } } void RemoveRemove(struct list* List){ char tmpword[33]; char tmppos[33]; unsigned char i; void (__stdcall *List_RemoveFirst)(struct list* List); void (__stdcall *List_RemoveLast) (struct list* List); void (__stdcall *List_RemoveValue)(char MD5[32], struct list* List, bool All); if (dllp) { List_RemoveFirst = (void(__stdcall *) (struct list* List)) GetProcAddress (dllp, "_List_RemoveFirst"); List_RemoveLast = (void(__stdcall *) (struct list* List)) GetProcAddress (dllp, "_List_RemoveLast"); List_RemoveValue = (void(__stdcall *) (char MD5[32], struct list* List, bool All)) GetProcAddress(dllp, "_List_RemoveValue"); } scanf("%s", tmppos); for (i = 0; i < 33; i++) tmppos[i] = toupper(tmppos[i]); if (slm(tmppos, "FIRST")) List_RemoveFirst(List); else if (slm(tmppos, "END")) List_RemoveLast(List); else if (slm(tmppos, "VAL")){ scanf("%s%s", tmppos, tmpword); for (i = 0; i < 33; i++){ tmpword[i] = toupper(tmpword[i]); tmppos[i] = toupper(tmppos[i]); } if (slm(tmppos, "RANDOM")) { RadndomMD5(); for (i = 0; i < 33; i++) tmppos[i] = toupper(tmp[i]); } if (slm(tmpword, "TRUE" )) List_RemoveValue(tmppos, List, true); else List_RemoveValue(tmppos, List, false); } } void PrintPrint(struct list* List){ void (__stdcall *List_PrintMe)(struct list* List); if (dllp) { List_PrintMe = (void(__stdcall *) (struct list* List)) GetProcAddress(dllp, "_List_PrintMe"); } List_PrintMe(List); } void CheckCheck(struct list* List){ bool (__stdcall *List_IsEmpty)(struct list* List); if (dllp) { List_IsEmpty = (bool(__stdcall *) (struct list* List)) GetProcAddress(dllp, "_List_IsEmpty"); } if (List_IsEmpty(List)) printf("true\n"); else printf("false\n"); } void FreeFree(struct list* List){ void (__stdcall *List_FreeAndNil)(struct list* List); if (dllp) { List_FreeAndNil = (void(__stdcall *) (struct list* List)) GetProcAddress(dllp, "_List_FreeAndNil"); } List_FreeAndNil(List); } int main(){ // Переменные bool exitkey; char tmpword[257]; int i; struct list* MyList; dllp = LoadLibrary("DinLib.dll"); struct list* (__stdcall *List_Create)(); // Начальная инициализация листа dllp = LoadLibrary("DinLib.dll"); if (dllp) { List_Create = (struct list*(__stdcall *) ()) GetProcAddress(dllp, "_List_Create"); } MyList = List_Create(); RadndomMD5(); // Фикс кириллицы SetConsoleOutputCP(1251); SetConsoleCP(1251); // Вывод приветствия printf("Добро пожаловать!\nПрограмму выполнил: Буренков Игорь (М80-206Б-17)\n\nведите h или help для вывода справки\n"); // Панель ввода вывода while (exitkey != true){ // Печать t> перед командой printf("t>"); // Считываем первое слово scanf("%s", tmpword); // Перевод слова в верхний регистр for (i = 0; i < 257; i++) tmpword[i] = toupper(tmpword[i]); // Анализ первой комманды if (slm(tmpword, "H")||slm(tmpword, "HELP")) PrintHelp(); else //if (slm(tmpword, "PRINT")) PrintPrint(MyList); else //if (slm(tmpword, "FIND")) FindFind(MyList); else //if (slm(tmpword, "CHECK")) CheckCheck(MyList); else //if (slm(tmpword, "ADD")) AddAdd(MyList); else //if (slm(tmpword, "REMOVE")) RemoveRemove(MyList); else //if (slm(tmpword, "CLEAN")) FreeFree(MyList); else if (slm(tmpword, "EXIT")) exitkey= true; } FreeFree(MyList); free(MyList); FreeLibrary(dllp); system("pause"); return 0; }
When a function is called, for example List_Add_First (tmp, List); the program crashes.
DLL is two files
mainlib.h:
#if defined(BUILD_DLL) # define DLL_EXP __declspec(dllexport) #else # if defined(BUILD_APP) # define DLL_EXP __declspec(dllimport) # else # define DLL_EXP # endif #endif // Стандартные заголовки #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <windows.h> #include <ctype.h> #include <string.h> // Структура листа struct listlight; // Структура листа struct list; // Создание узла листа DLL_EXP struct list* List_Create(); // Уничтожение листа DLL_EXP void List_FreeAndNil(struct list* List); // Проверка на пустоту DLL_EXP bool List_IsEmpty(struct list* List); // Добавить элемент-лист в начало DLL_EXP void List_Add_First(char MD5[32], struct list* List); // Добавить элемент-лист в конец DLL_EXP void List_Add_End(char MD5[32], struct list* List); // Удаление первого листа DLL_EXP void List_RemoveFirst(struct list* List); // Удаление последнего листо DLL_EXP void List_RemoveLast(struct list* List); // Удаление листа по значениею DLL_EXP void List_RemoveValue(char MD5[32], struct list* List, bool All); // Поиск значения DLL_EXP bool List_FindMe(char MD5[32], struct list* List); // Печать элементы DLL_EXP void List_PrintMe(struct list* List);
mainlib.c:
#define BUILD_DLL #include "mainlib.h" // Структура листа struct listlight { char MD5[33]; // MD5 struct listlight* right; // Правый ребенок }; // Структура листа struct list { struct listlight* first; }; // Создание листа DLL_EXP struct list* List_Create(){ struct list* List = malloc(sizeof(struct list)); List->first = NULL; return List; } // Уничтожение листа DLL_EXP void List_FreeAndNil(struct list* List) { // Запускаем балалайку ^_^ //while (List_IsEmpty(List) == false) { // List_RemoveLast(List); //} return; } // Проверка на пустоту DLL_EXP bool List_IsEmpty(struct list* List){ return (List->first == NULL); } // Инициализация элемента списка DLL_EXP struct listlight* Leaf_inside_Create(char MD5[32]){ // Переменные struct listlight* tmp; unsigned char i; // Начальная инициализация tmp = malloc(sizeof(struct listlight)); tmp->right = NULL; for (i = 0; i < 33; i++) tmp->MD5[i] = MD5[i]; // Возращаем указатель return tmp; } // Добавление листа в конец DLL_EXP void List_Add_End(char MD5[33], struct list* List){ // Указатель на новый элемент struct listlight* tmp = Leaf_inside_Create(MD5); struct listlight* current; // Вставляем указатель if (List_IsEmpty(List)) { List->first = tmp; } else { current = List->first; while (current->right != NULL) current = current->right; current->right = tmp; } } // Добавление листа в начало DLL_EXP void List_Add_First(char MD5[33], struct list* List){ // Указатель на новый элемент struct listlight* tmp = Leaf_inside_Create(MD5); // Временный контейнер struct listlight* current; // Вставляем указатель if (List_IsEmpty(List)) { List->first = tmp; } else { tmp->right = List->first; List->first = tmp; } } // Удаление первого элемента DLL_EXP void List_RemoveFirst(struct list* List){ // Временный контейнер struct listlight* tmp; // Если лист не пустой if (List_IsEmpty(List) == false) { // Запоминаем 2ю позицию tmp = List->first->right; // Освобождение памяти free(List->first); // Делаем 2ю позицию первой List->first = tmp; } } // Удаление последнего элемента DLL_EXP void List_RemoveLast(struct list* List){ // Временный контейнер struct listlight* tmp = List->first; if (tmp == NULL) return; if (tmp->right == NULL) { List_RemoveFirst(List); return; } while (tmp->right->right != NULL) tmp = tmp->right; free(tmp->right); tmp->right = NULL; } //Сравнить две MD5 суммы DLL_EXP bool EquivalentMD5(char MD5left[33], char MD5right[33]){ unsigned char i; for (i = 0; i < 33; i++) if (MD5left[i] != MD5right[i]) return false; return true; } // Удалить по значению DLL_EXP void List_RemoveValue(char MD5[33], struct list* List, bool All){ // Переменные unsigned char i; struct listlight* tmp = List->first; struct listlight* tmp2; if (tmp == NULL) return; if (EquivalentMD5(tmp->MD5, MD5)) { List_RemoveFirst(List); if (All == false) return; } while (tmp->right != NULL){ if (EquivalentMD5(tmp->right->MD5, MD5)) { if (tmp->right->right == NULL) List_RemoveLast(List); else{ tmp2 = tmp->right->right; free(tmp->right); tmp->right = tmp2; } if (All == false) return; } } } // Поиск значения DLL_EXP bool List_FindMe(char MD5[33], struct list* List){ struct listlight* tmp = List->first; while (tmp != NULL){ if (EquivalentMD5(tmp->MD5, MD5)) return true; tmp = tmp->right; } return false; } // Печать элементы DLL_EXP void List_PrintMe(struct list* List){ struct listlight* tmp = List->first; unsigned char i; while (tmp != NULL){ printf("%c", '|'); for (i = 0; i < 33; i++) { printf("%c", tmp->MD5[i]); } tmp = tmp->right; } printf("%c%c", '|', '\n'); }
If you connect this library as .lib (static) - everything works, but as a dll, for some reason it does not.
Link to the project: https://yadi.sk/d/390OeXKfXdiBcg (Static - .lib, Unstatic - .dll)
I sincerely hope for your help, because I'm just learning how to work with such libraries and maybe I don't understand something.
BUILD_APP
symbolBUILD_APP
? Where is it used? And why do you have#define BUILD_DLL
at the beginning of the main program ??? - AnTstruct list* List_Create();
, and in the EXEstruct list* (__stdcall *List_Create)();
. Where did __stdcall come from? - MSDN.WhiteKnight