Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Компоновщик не знает OpenFileNameA

27K
11 декабря 2013 года
mnanorn
78 / / 01.12.2013
Здравствуйте!

В главной функции пишу:

Код:
...
ZeroMemory(&ofn , sizeof( ofn));
ofn.lStructSize = sizeof ( ofn );
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '�';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All�*.*�Text�*.TXT�";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL ;
ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
GetOpenFileName(&ofn);

MessageBox ( NULL , ofn.lpstrFile , "File Name" , MB_OK);
...
Получаю ошибку:
 
Код:
openfile.o:openfile.c|| undefined reference to `GetOpenFileNameA@4'
Самое интересное, что, например, MessageBox() он воспринял. Компилятор - MinGW. У кого какие мысли?

Спасибо за Ваше внимание.
326
12 декабря 2013 года
sadovoya
757 / / 19.11.2005
Линковщику надо добавить такую библиотеку:
MinGW\lib\libcomdlg32.a
326
12 декабря 2013 года
sadovoya
757 / / 19.11.2005
Меня подобные проблемы с Win API давно достали и все чаще использую "ручную" загрузку ф-ций из системных библиотек. Для этого написал крохотный класс-обертку, который подключаю к проектам. Очень удобно: достаточно в MSDN посмотреть название dll-файла, где описана нужная api-функция и ее прототип. Иногда надо и структуры скопировать, но они в заголовочниках могут и быть, даже, если самой ф-ции нет. Иногда наоборот бывает. Но как бы там ни было, но класс жизнь облегчает.
Приведу пример на базе вашей задачи. Может пригодится. Класс здесь в минимальной реализации, можно его развить.

Код:
#include <iostream>
#include <windows.h>

using namespace std;

class DllHandler {
    HINSTANCE hDLL; // Handle для DLL (NULL - не загружена)
    //прячим в privat конструктор копий и =
    DllHandler(const DllHandler &);
    DllHandler & operator=(const DllHandler &);
public:
    DllHandler(const char dll_name[]) { // конструктор принимает имя dll
        hDLL = LoadLibraryA(dll_name);
    }
    ~DllHandler() {
        freeDll();
    }
    BOOL isLoaded() { // проверка загруженности dll
        if (hDLL) return true;
        else return false;
    }
    void *getFun(const char fun_name[]) { // получить ф-цию из dll по ее имени
        void *vp = NULL;
        if (hDLL) vp = (void *)GetProcAddress(hDLL, fun_name);
        return vp;
    }
    void freeDll() { // выгрузка dll
        if (hDLL) if (FreeLibrary(hDLL)) hDLL = NULL;
    }
};

int main() {

    OPENFILENAMEA ofn;
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof (ofn);
    //......
    typedef BOOL WINAPI(*FUN)(LPOPENFILENAMEA);
    DllHandler hComdlg32("Comdlg32.dll");
    FUN fn = (FUN)hComdlg32.getFun("GetOpenFileNameA");
    if(fn)
        fn(&ofn);
    else
        MessageBoxA(0, "Ошибка открытия библиотеки или ф-ция отсутствует", "", 0);

    return 0;
}
27K
12 декабря 2013 года
mnanorn
78 / / 01.12.2013
Цитата: sadovoya
Линковщику надо добавить такую библиотеку:
MinGWliblibcomdlg32.a


Большое спасибо. А что это за библиотека? Commctl32 знаю, а эту нет.

326
14 декабря 2013 года
sadovoya
757 / / 19.11.2005
Это Common Dialog Box Library -- библиотека основных диалогов. Начиная с Vista рекомендуют для Open и Save использовать более современные API (из Common Item Dialog).
326
10 марта 2014 года
sadovoya
757 / / 19.11.2005
Если кому интересно. В С++11 можно работать с dll в рантайме еще удобней. Вот пример, надеюсь ничего не напортачил (пока не силен в 11-ом стандарте):

Код:
#include <cstdio>
#include <windows.h>
#include <memory> //std::unique_ptr

int main() {
    auto lambda_deleater = [](HMODULE* instance) {
        FreeLibrary(*instance);
        delete instance;
    };
    auto dll_u_ptr = std::unique_ptr<HMODULE, decltype(lambda_deleater)>
                       (new HMODULE(LoadLibrary(TEXT("kernel32.dll"))), lambda_deleater);

    using FUN = void (CALLBACK* )(LPMEMORYSTATUS);
    auto dll_func = (FUN)GetProcAddress(*dll_u_ptr, "GlobalMemoryStatus");

    MEMORYSTATUS ms;
    dll_func(&ms);
    printf("Mem. load is %lu %%\nPress any key...", ms.dwMemoryLoad);
    getchar();

    return 0;
}
Аналогично можно с shared pointer-ом.
За основу взял материал habrahabr.ru/post/207842/ (пост и комментарии к нему).
326
16 марта 2014 года
sadovoya
757 / / 19.11.2005
Поскольку HINSTANCE и HMODULE -- это (void *) (см. в MSDN здесь), /то можно сделать код лучше, вообще избавившись от new/delete:

 
Код:
...
auto lambda_deleter = [](void* hM) { FreeLibrary( (HMODULE)hM ); };
auto dll_u_ptr = std::unique_ptr<void, decltype(lambda_deleter)>
                     (LoadLibraryA("kernel32.dll"), lambda_deleter);
...
using FUN = void (CALLBACK* )(LPMEMORYSTATUS);
auto dll_func = (FUN)GetProcAddress((HINSTANCE)dll_u_ptr.get(), "GlobalMemoryStatus");
...
В комментариях на habrahabr.ru/post/207842/ подобное тоже обсуждалось.

Еще можно более кратко, но не уверен, что правильно:

 
Код:
...
auto dll_u_ptr = std::unique_ptr<HINSTANCE__, decltype(&FreeLibrary)>
                     (LoadLibraryA("kernel32.dll"), &FreeLibrary);
...
auto dll_func = (FUN)GetProcAddress(dll_u_ptr.get(), "GlobalMemoryStatus");
...
Это основано на догадке, что (HINSTANCE__*) -- это и есть HINSTANCE. Код работает, но сомнения есть.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог