Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Dll Unicode ошибка Linker'а


Автор: UfoLand 7.2.2008, 19:48
Решил,тут, перевести проект на UNICODE, делал-делал, но столкнулся с проблемой,
использую стороннюю библиотеку(собрана на VC6++), при сборке проекта получаю ошибку вида

Код

error LNK2001: unresolved external symbol "public: int __thiscall CUserLib::SetKey(wchar_t const *)" (?SetKey@CUserLib@@QAEHPB_W@Z)    Client.obj


Метод:
Код

BOOL SetKey(LPCTSTR sKey);


Вызываю:
Код

SetKey(LPCTSTR("KEY"));



Пробовал поставить в свойствах проекта (/Zc:wchar_t-) - не помогло.

Что делать?-)

Автор: JackYF 7.2.2008, 20:08
UfoLand, а у тебя-то компилятор какой?

Автор: marcusmae 7.2.2008, 21:49
UfoLand, скорее всего несоответствие соглашения о вызове (thiscall, stdcall, cdecl) - в данном случае - нужно thiscall (в ошибке об этом сказано). А как Вы анонсируете метод у себя в программе, то есть что написано в хедере? Кроме того, имя функции декорировано. С помощью dumpbin и подобных утилит Вы можете узнать, действительно ли сторонняя библиотека эспортируют функцию, которую хотите использовать. И подключена ли она вообще, то есть работают ли какие-либо другие функции...

А тип параметра верен (если символ препроцессора _UNICODE определён).

Автор: 586 10.2.2008, 02:00
Цитата(UfoLand @  7.2.2008,  19:48 Найти цитируемый пост)
SetKey(LPCTSTR("KEY"));

Нельзя так делать!
Код
SetKey(TEXT("KEY"));

Автор: UfoLand 12.2.2008, 14:03
Цитата(JackYF @  7.2.2008,  20:08 Найти цитируемый пост)
UfoLand, а у тебя-то компилятор какой? 


Setting environment for using Microsoft Visual Studio 2005 x86 tools.

C:\Program Files\Microsoft Visual Studio 8\vc\bin>cl
Microsoft ® 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

Copyright © Microsoft Corporation.  All rights reserved.


Цитата(marcusmae @  7.2.2008,  21:49 Найти цитируемый пост)
А как Вы анонсируете метод у себя в программе, то есть что написано в хедере?

НУ просто подключаю библиотеку и заголовочный файл(там этот метод и обявлен):


Код

// UserLib.h: interface for the CUserLib class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_USERLIB_H__A370F557_2178_4F9E_8B8C_8C2554A94C55__INCLUDED_)
#define AFX_USERLIB_H__A370F557_2178_4F9E_8B8C_8C2554A94C55__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CUserObject;

class CUserLib  
{
public:
    CUserLib();
    ~CUserLib();
....
....
....
        BOOL SetKey(LPCTSTR sKey);
};
#endif // !defined(AFX_USERLIB_H__A370F557_2178_4F9E_8B8C_8C2554A94C55__INCLUDED_)

Цитата(marcusmae @  7.2.2008,  21:49 Найти цитируемый пост)
действительно ли сторонняя библиотека эспортируют функцию, которую хотите использовать.


Я этой функцией свободно пользовался до того как перейти на юникод, у меня вообще проектр собирался ии всё было в порядк, до перехода на юникод.

Цитата(marcusmae @  7.2.2008,  21:49 Найти цитируемый пост)
И подключена ли она вообще, то есть работают ли какие-либо другие функции...

Да работают другие функции, ошибки Linker'а вылезают только у функций где в качестве параметра должна передаваться как минимум одна строка LPCTSTR


Цитата(marcusmae @  7.2.2008,  21:49 Найти цитируемый пост)
А тип параметра верен (если символ препроцессора _UNICODE определён).

Я когда решил перейти на юникод, выставил в свойствах проекта: Use Unicode Character Set
пробовал и _UNICODE - руками прописать, не помогло...

Цитата(marcusmae @  7.2.2008,  21:49 Найти цитируемый пост)
скорее всего несоответствие соглашения о вызове (thiscall, stdcall, cdecl) - в данном случае - нужно thiscall (в ошибке об этом сказано)

как это реализовать, подскажите пож-ста...

Цитата(586 @  10.2.2008,  02:00 Найти цитируемый пост)

SetKey(TEXT("KEY"));

Такой вариант я то же пробовал, результат одни...


Автор: marcusmae 12.2.2008, 15:28
UfoLand, кажется, я понял, в чём тут дело. Смотрите, может в своём проекте Вы определили символ _UNICODE, но это никак не влияет на юникодовость подключаемой библиотеки. LPCTSTR - это условный алиас, он равен LPCWSTR (const wchar_t*) если _UNICODE или LPCASTR (const char*) иначе. То есть, если в САМОЙ библиотеке не определён юникод, то в ней функция имеет прототип

Код

BOOL SetKey(const char* sKey);


а Вы пытаетесь вызвать

Код

BOOL SetKey(const wchar_t* sKey);


которого там ессесно нет.

Есть ли возможность пересобрать саму библиотеку с _UNICODE?

Автор: xvr 13.2.2008, 14:53
Цитата(UfoLand @ 12.2.2008,  14:03)
Цитата(JackYF @  7.2.2008,  20:08 Найти цитируемый пост)
UfoLand, а у тебя-то компилятор какой? 


Setting environment for using Microsoft Visual Studio 2005 x86 tools.

C:\Program Files\Microsoft Visual Studio 8\vc\bin>cl
Microsoft ® 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

Copyright © Microsoft Corporation.  All rights reserved.


Цитата(marcusmae @  7.2.2008,  21:49 Найти цитируемый пост)
А как Вы анонсируете метод у себя в программе, то есть что написано в хедере?

НУ просто подключаю библиотеку и заголовочный файл(там этот метод и обявлен):


Код

// UserLib.h: interface for the CUserLib class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_USERLIB_H__A370F557_2178_4F9E_8B8C_8C2554A94C55__INCLUDED_)
#define AFX_USERLIB_H__A370F557_2178_4F9E_8B8C_8C2554A94C55__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CUserObject;

class CUserLib  
{
public:
    CUserLib();
    ~CUserLib();
....
....
....
        BOOL SetKey(LPCTSTR sKey);
};
#endif // !defined(AFX_USERLIB_H__A370F557_2178_4F9E_8B8C_8C2554A94C55__INCLUDED_)


Гы, сторонняя библиотека ТОЖЕ должна быть откомпилированна в Unicode!

Автор: Adil' 13.2.2008, 18:09
Если библ-ку нельзя пересобрать с поддержкой unicode, можно попробовать "обрамить" подключаемые заголовочные файлы, типа:
Код
#ifdef _UNICODE
  #undef _UNICODE
    #include "..."
  #define _UNICODE
#else
    #include "..."
#endif

Автор: marcusmae 13.2.2008, 19:52
Цитата(Adil' @  13.2.2008,  18:09 Найти цитируемый пост)
Если библ-ку нельзя пересобрать с поддержкой unicode, можно попробовать "обрамить" подключаемые заголовочные файлы, типа:


Adil', а толку? = Заголовочные файлы могут быть какими угодно. Но содержимое dll от этого не изменится : если dll с _UNICODE, а header - без или dll без _UNICODE, а хедер - с ним, то нужные функции найдены не будут. Так что либо два комплекта хедер + dll для каждой из версий, либо два хедера и один dll, в котором реализуются оба варианта, либо то, что, имхо, лучше всего : не разводить лишних хедеров и иметь в dll обе реализации

Код

// dll
BOOL SetKey(const char* sKey);
BOOL SetKey(const wchar_t* sKey);


и ОДИН хедер, в котором переключение между двумя вариантами спрятано в LPCTSTR :

Код

// header
BOOL SetKey(LPCTSTR sKey);


Автор: 586 13.2.2008, 21:23
Цитата(UfoLand @  7.2.2008,  19:48 Найти цитируемый пост)
Вызываю:
Код
SetKey(LPCTSTR("KEY"));

Цитата(xvr @  13.2.2008,  14:53 Найти цитируемый пост)
class CUserLib  
{
public:
    CUserLib();
    ~CUserLib();
....
....
....
        BOOL SetKey(LPCTSTR sKey);
};


Если метод реализован в DLL, я не вижу, что он экспортируется.
Код
#ifdef __DLL__
#define _exp_    extern __declspec(dllexport)
#else
#define _exp_    extern __declspec(dllimport)
#endif

class CUserLib  
{
public:
    CUserLib();
    ~CUserLib();
....
....
....
      _exp_ BOOL SetKey(LPCTSTR sKey);
};

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)