Помогите подключить dll в VC6
От: Vold Россия  
Дата: 23.09.02 03:06
Оценка:
Помогите победить DLL

Здравствуйте! Я пишу на VC++ 6 и у меня возникла проблема с подключением длл.
С раньше основном работал с айпишными библиотеками, но там все делается на автомате и никаких особых проблем не возникало, а сейчас появилась необходимость расчитывать хэш-функцию файла используя библиотеку put_hash.dll (put_hash.h put_hash.lib)
При попытке подключить библиотеку статически, выдает сообщение «Заголовок .либ файла поврежден или не верен».
Тогда я попытался подключить функции динамически. Посмотрел пример из MSDN и начал:

typedef INT (*MYPROC)(LPTSTR);
typedef INT (*MYPROC2)(LPTSTR, LPTSTR, LPINT, LPINT);

HINSTANCE hDLL;
MYPROC ProcAdd;
MYPROC2 ProcAdd2;
lptstr pathname="d:\\test.htm";
lptstr hash;

    hDLL=LoadLibrary("put_hash.dll");
    if(hDLL!=NULL)
    {
     ProcAdd=(MYPROC)GetProcAddress(hDLL,"InitPUT_HASH");
     (ProcAdd);
     ProcAdd2=(MYPROC2)GetProcAddress(hDLL,"MakeHashFile");
     (ProcAdd2)(pathname, hash, os_error, hash_error);
     ProcAdd=(MYPROC)GetProcAddress(hDLL,"DonePUT_HASH");
     (ProcAdd);
    }
    FreeLibrary(hDLL);


Из put_hash.h
/*
  pathname - полное имя файла
  hash - значение хеш функции пpеобpазованное в стpоку в шестнадцатеpичном
         фоpмате
  os_error - код ошибки ОС или 0
  hash_error - код ошибки функции или 0
  Возвpат 0 - ОК
          #0 - когда hash_error или os_error #0

*/

int PASCAL CALLBACK _export MakeHashFile(
  lptstr pathname,
  lptstr hash,
  lpint os_error,
  lpint hash_error);


В этом случае у меня появилась ошибка “Unhandled exception” при вызове функции MakeHashFile. Когда я посмотрел дллку через быстрый просмотр, оказалось что GetProcAddress возвращает адрес совсем другой функции! (т.е. Entry Point у InitPUT_HASH 0x0000e82c, а у @__lockDebuggerData$gv 0x00003329. GetProcAddress(hDLL,”InitPUT_HASH”) возвращает 0x00883329!)
Помучавшись, я стал задавать адреса напрямую:
     ProcAdd=(MYPROC)0x0088e82c;
     ProcAdd2=(MYPROC2)0x008856d4;


В этом случае все проходит нормально, ошибок нет, но и результата работы тоже нет!
По идее функция должна записывать в hash высчитанную хэш-функцию файла.
Бьюсь уже неделю! Подскажите, что я неправильно делаю? Может библиотека битая?
Может у меня руки кривые?
Re: Помогите подключить dll в VC6
От: Alex Fedotov США  
Дата: 23.09.02 03:53
Оценка:
Здравствуйте Vold, Вы писали:

V>Помогите победить DLL


V>Здравствуйте! Я пишу на VC++ 6 и у меня возникла проблема с подключением длл.

V>С раньше основном работал с айпишными библиотеками, но там все делается на автомате и никаких особых проблем не возникало, а сейчас появилась необходимость расчитывать хэш-функцию файла используя библиотеку put_hash.dll (put_hash.h put_hash.lib)
V>При попытке подключить библиотеку статически, выдает сообщение «Заголовок .либ файла поврежден или не верен».
V>Тогда я попытался подключить функции динамически. Посмотрел пример из MSDN и начал:

V>typedef INT (*MYPROC)(LPTSTR);
V>typedef INT (*MYPROC2)(LPTSTR, LPTSTR, LPINT, LPINT);


Судя по тому, что написано в put_hash.h, правильный прототип будет

typedef INT (CALLBACK *MYPROC)(LPSTR);
typedef INT (CALLBACK *MYPROC2)(LPSTR, LPSTR, LPINT, LPINT);


V>HINSTANCE hDLL;
V>MYPROC ProcAdd;
V>MYPROC2 ProcAdd2;
V>lptstr pathname="d:\\test.htm";
V>lptstr hash;

V>    hDLL=LoadLibrary("put_hash.dll");
V>    if(hDLL!=NULL)
V>    {
V>     ProcAdd=(MYPROC)GetProcAddress(hDLL,"InitPUT_HASH");


Строчка ниже не выглядит как вызов функции по указателю.

V>     (ProcAdd);


Правильно будет

         (*ProcAdd)();   // C style
         ProcAdd();      // C++ style
         (ProcAdd)();    // no style but works


V>     ProcAdd2=(MYPROC2)GetProcAddress(hDLL,"MakeHashFile");
V>     (ProcAdd2)(pathname, hash, os_error, hash_error);
V>     ProcAdd=(MYPROC)GetProcAddress(hDLL,"DonePUT_HASH");
V>     (ProcAdd);
V>    }
V>    FreeLibrary(hDLL);
V>
-- Alex Fedotov
Re: Помогите подключить dll в VC6
От: Alex Fedotov США  
Дата: 23.09.02 03:57
Оценка: 2 (1)
Здравствуйте Vold, Вы писали:

V>Помогите победить DLL


В догонку. Рекомендуется к прочтению
http://www.rsdn.ru/?article/default.asp?baseserv/dlluse.xml
Автор(ы):
Александр Шаргин


В статье рассматривается три способа подключения DLL к программе на Visual C++ — неявное подключение (implicit linking), явное подключение (explicit linking) и отложенная загрузка (delayed load) DLL. Для каждого способа демонстрируется использование переменной, функции и класса из подключаемой DLL. В разделе об отложенной загрузке также приводится дополнительная информация (описание обработки исключений и использования функций-ловушек).
-- Alex Fedotov
Re[2]: Помогите подключить dll в VC6
От: Vold Россия  
Дата: 23.09.02 06:15
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>Судя по тому, что написано в put_hash.h, правильный прототип будет


AF>
AF>typedef INT (CALLBACK *MYPROC)(LPSTR);
AF>typedef INT (CALLBACK *MYPROC2)(LPSTR, LPSTR, LPINT, LPINT);
AF>

Спасибо за подсказку! Так действительно правильно и функции хоть стали возвращать значения (возвращает 0, т.е. отсутствие ошибки), но основную задачу не выполняет

Все таки меня смущает разница ссылок на функции библиотеки (адрес который мне указывает дебагер и адрес который указан при быстром просмотре).

При вызове основной функции MakeHashFile она опять таки возвращает ноль, но внизу в окне сообщений дебага выдает сообщение "First-chance exception in hash.exe: (KERNEL32.DLL): 0xC0000005: Access Violation"

Спасибо за ссылку на статью, но из-за либ файла мне подходит только явное подключение. Пробовал программу DLL to LIB, писал .dif файл, но тоже ничего не получилось Мне уже проще начальнику сказать что библиотека битая, уж больно я на ней много времени потерял
Re[3]: Помогите подключить dll в VC6
От: Alex Fedotov США  
Дата: 23.09.02 06:49
Оценка: 2 (1)
Здравствуйте Vold, Вы писали:

V>Спасибо за подсказку! Так действительно правильно и функции хоть стали возвращать значения (возвращает 0, т.е. отсутствие ошибки), но основную задачу не выполняет :(


Вот этот код работает на моей системе: в szHash заносится нечто, похожее на хэш файла.

int 
_tmain(
    int argc, 
    _TCHAR * argv[]
    )
{
    HINSTANCE hInstance = LoadLibrary(_T("put_hash.dll"));
    if (hInstance == NULL)
        return -1;

    INT (CALLBACK * pInitPUT_HASH)();
    VOID (CALLBACK * pDonePUT_HASH)();
    INT (CALLBACK * pMakeHashFile)(PCSTR, PCSTR, PINT, PINT);

    *(FARPROC *)&pInitPUT_HASH = GetProcAddress(hInstance, "InitPUT_HASH");
    *(FARPROC *)&pDonePUT_HASH = GetProcAddress(hInstance, "DonePUT_HASH");
    *(FARPROC *)&pMakeHashFile = GetProcAddress(hInstance, "MakeHashFile");

    if (pInitPUT_HASH == NULL ||
        pDonePUT_HASH == NULL ||
        pMakeHashFile == NULL)
        return -1

    INT nRet, nOsErr, nHashErr;
    CHAR szHash[MAX_PATH];
    
    nRet = pInitPUT_HASH();
    if (nRet != 0)
        return nRet;

    nRet = pMakeHashFile("D:\\dxdiag.txt", szHash, &nOsErr, &nHashErr);

    pDonePUT_HASH();

    return nRet;
}


V>Все таки меня смущает разница ссылок на функции библиотеки (адрес который мне указывает дебагер и адрес который указан при быстром просмотре).


Не верь быстрому просмотру, верь depends.exe. Адрес InitPUT_HASH — 0x00003329 относительно адреса загрузки DLL.

V>При вызове основной функции MakeHashFile она опять таки возвращает ноль, но внизу в окне сообщений дебага выдает сообщение "First-chance exception in hash.exe: (KERNEL32.DLL): 0xC0000005: Access Violation"


Это может быть признаком ошибки, а может и не быть.
-- Alex Fedotov
Re[4]: Большое человеческое спасибо!!!
От: Vold Россия  
Дата: 23.09.02 08:25
Оценка:
В Вин98 тоже работает! Спасибо за советы! Жалко нельзя пиво в аттачменте отправить

Эх! Учить мне еще указатели — не переучить!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.