Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/29: Рейтинг темы: голосов - 29, средняя оценка - 4.55
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
1

Как отменить действие макроса UNICODE?

19.09.2014, 19:08. Показов 5258. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C++
1
#undef UNICODE
не работает. Но всё по порядку.

Друзья! Недавно качнул один из компиляторов компилятор gcc, вот начинаю работать.

Создал диалоговое окно (конструктором форм), но хоть код и минимальный, но файлов с исходниками несколько, все их не выкладываю поэтому. Есть там такая функция:

C++
1
2
3
4
5
void* taskl(void* X)
{
    WIN32_FIND_DATA FindFileData;
    FindFirstFile("path",&FindFileData);
}
Ошибка:

Bash
1
36 C:\Documents and Settings\ser\Рабочий стол\np\prDlg.cpp:109 cannot convert 'const char*' to 'LPCWSTR {aka const wchar_t*}' for argument '1' to 'void* FindFirstFileW(LPCWSTR, LPWIN32_FIND_DATAW)'
Обращаю внимание, препроцессор заменяет FindFirstFile на FindFirstFileW, что в моей ситуации недопустимо- я предполагаю компилить уже имеющийся код, его править не получится. Нужно отменять юникод. Лезу в Winbase.h:

C++
1
2
3
4
5
6
7
8
9
#ifdef UNICODE
//всякие макросы
#define FindFirstFile FindFirstFileW
//всякие макросы
#else
//всякие макросы
#define FindFirstFile FindFirstFileA
//всякие макросы
#endif
То есть вывод: где-то у меня определён макрос UNICODE (где не знаю, я работаю с конструктором форм, он сам видать где-то определил), надо отменить этот макрос:

C++
1
2
3
4
5
6
void* taskl(void* X)
{
    #undef UNICODE
    WIN32_FIND_DATA FindFileData;
    FindFirstFile("path",&FindFileData);
}
та же ошибка. ЧЯДНТ? Мне кажется, нужно в определённом месте отменять подобные макросы, но в каком? Так-то раньше бы я просто закомментил ненужное в Winbase.h и всё на этом. Но нужно научиться грамотно это всё делать . Спасибо, кто откликнется. Здесь прочёл.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.09.2014, 19:08
Ответы с готовыми решениями:

Как отменить действие макроса
Добрый день, есть большой макрос, который выполняет с текстом множество операций. Существует ли...

Как отменить действие обработчика?
Добрый вечер. Возник такой вопрос, можно ли по клику на кнопку отменить предыдущую обработку...

Как отменить действие стиля?
В главном html таблица красится через tbody tr:nth-child(odd) Присоединяю по событию другой html и...

Как отменить следующие действие
Через Form1 вызывается Form2, после закрытия Form2 выполняется действие. На Form2 есть button1 и...

15
22 / 25 / 11
Регистрация: 10.10.2013
Сообщений: 165
19.09.2014, 20:13 2
Все "макросовые" дефайны, насколько я знаю, делаются в самом самом верху над инклюдами.

Добавлено через 1 минуту
А, еще попробуйте настройки проекта посмотреть.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
19.09.2014, 21:22 3
Как уже сказал inst_mefi имеет смысл менять в свойствах проекта. Ну а тут
C++
1
2
3
#undef UNICODE
WIN32_FIND_DATA FindFileData;
FindFirstFile("path",&FindFileData);
от #undef проку нет, потому что FindFirstFile уже развернулся в соответствующую версию во время инклюда упомянутого Winbase.h. Т.е. если хочется поиграть макросами вручную надо делать undef UNICODE до подключения хидеров, в которых этот UNICODE анализируется.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
19.09.2014, 22:09  [ТС] 4
Цитата Сообщение от inst_mefi Посмотреть сообщение
А, еще попробуйте настройки проекта посмотреть.
не помогло.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++

Цитата Сообщение от Tulosba Посмотреть сообщение
вручную надо делать undef UNICODE до подключения хидеров, в которых этот UNICODE анализируется.
а где он может анализироваться? Мест не так много на самом деле. В проекте образуются два хидера, вот они:

prApp.h
//---------------------------------------------------------------------------
//
// Name: prApp.h
// Author: ser
// Created: 19.09.2014 10:10:07
// Description:
//
//---------------------------------------------------------------------------

#ifndef __PRDLGApp_h__
#define __PRDLGApp_h__

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include <wx/wx.h>
#else
#include <wx/wxprec.h>
#endif

class prDlgApp : public wxApp
{
public:
bool OnInit();
int OnExit();
};

#endif


prDlg.h
///-----------------------------------------------------------------
///
/// @file prDlg.h
/// @author ser
/// Created: 19.09.2014 10:10:07
/// @section DESCRIPTION
/// prDlg class declaration
///
///------------------------------------------------------------------

#ifndef __PRDLG_H__
#define __PRDLG_H__

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP

#include <wx/wx.h>
#include <wx/dialog.h>
#else
#include <wx/wxprec.h>
#endif

//Do not add custom headers between
//Header Include Start and Header Include End.
//wxDev-C++ designer will remove them. Add custom headers after the block.
////Header Include Start
////Header Include End


////Dialog Style Start
#undef prDlg_STYLE
#define prDlg_STYLE wxCAPTION | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxMINIMIZE_BOX | wxCLOSE_BOX
////Dialog Style End

class prDlg : public wxDialog
{
private:
DECLARE_EVENT_TABLE();

public:
prDlg(wxWindow *parent, wxWindowID id = 1, const wxString &title = wxT("pr"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = prDlg_STYLE);
virtual ~prDlg();
void prDlgActivate(wxActivateEvent& event);
void prDlgActivateApp(wxActivateEvent& event);
void prDlgEnterWindow(wxMouseEvent& event);

private:
//Do not add custom control declarations between
//GUI Control Declaration Start and GUI Control Declaration End.
//wxDev-C++ will remove them. Add custom code after the block.
////GUI Control Declaration Start
////GUI Control Declaration End

private:
//Note: if you receive any error with these enum IDs, then you need to
//change your old form code that are based on the #define control IDs.
//#defines may replace a numeric value for the enum names.
//Try copy and pasting the below block in your old form header files.
enum
{
////GUI Enum Control ID Start
////GUI Enum Control ID End
ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values
};

private:
void OnClose(wxCloseEvent& event);
void CreateGUIControls();
};

#endif





А в них в общей сложности существует 5 подключений как бы внешних хидеров, идущих в комплекте с компилятором.
C++
1
2
3
4
5
#include <wx/wx.h>
#include <wx/wxprec.h>
#include <wx/wx.h>
#include <wx/dialog.h>
#include <wx/wxprec.h>
подключение условное, но дабы в нём не разбираться, я просто написал #undef UNICODE перед КАЖДЫМ из пяти подключений. Всего-навсего. Вот так:

prApp.h
//---------------------------------------------------------------------------
//
// Name: prApp.h
// Author: ser
// Created: 19.09.2014 10:10:07
// Description:
//
//---------------------------------------------------------------------------

#ifndef __PRDLGApp_h__
#define __PRDLGApp_h__

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#undef UNICODE
#include <wx/wx.h>
#else
#undef UNICODE
#include <wx/wxprec.h>
#endif

class prDlgApp : public wxApp
{
public:
bool OnInit();
int OnExit();
};

#endif


prDlg.h
///-----------------------------------------------------------------
///
/// @file prDlg.h
/// @author ser
/// Created: 19.09.2014 10:10:07
/// @section DESCRIPTION
/// prDlg class declaration
///
///------------------------------------------------------------------

#ifndef __PRDLG_H__
#define __PRDLG_H__

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#undef UNICODE
#include <wx/wx.h>
#undef UNICODE
#include <wx/dialog.h>
#else
#undef UNICODE
#include <wx/wxprec.h>
#endif

//Do not add custom headers between
//Header Include Start and Header Include End.
//wxDev-C++ designer will remove them. Add custom headers after the block.
////Header Include Start
////Header Include End


////Dialog Style Start
#undef prDlg_STYLE
#define prDlg_STYLE wxCAPTION | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxMINIMIZE_BOX | wxCLOSE_BOX
////Dialog Style End

class prDlg : public wxDialog
{
private:
DECLARE_EVENT_TABLE();

public:
prDlg(wxWindow *parent, wxWindowID id = 1, const wxString &title = wxT("pr"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = prDlg_STYLE);
virtual ~prDlg();
void prDlgActivate(wxActivateEvent& event);
void prDlgActivateApp(wxActivateEvent& event);
void prDlgEnterWindow(wxMouseEvent& event);

private:
//Do not add custom control declarations between
//GUI Control Declaration Start and GUI Control Declaration End.
//wxDev-C++ will remove them. Add custom code after the block.
////GUI Control Declaration Start
////GUI Control Declaration End

private:
//Note: if you receive any error with these enum IDs, then you need to
//change your old form code that are based on the #define control IDs.
//#defines may replace a numeric value for the enum names.
//Try copy and pasting the below block in your old form header files.
enum
{
////GUI Enum Control ID Start
////GUI Enum Control ID End
ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values
};

private:
void OnClose(wxCloseEvent& event);
void CreateGUIControls();
};

#endif


Так ведь не помогло! Так куда же прописывать #undef UNICODE? В штатные хидеры лезть своими толстыми пальцами, как я делал раньше, это нехорошо. Ради этого и тему такую создавать не следовало.
0
22 / 25 / 11
Регистрация: 10.10.2013
Сообщений: 165
19.09.2014, 22:17 5
kravam, в начале каждого файла, где есть #include <something(файл созданный не вами)> напишите #undef UNICODE. Упрощая слова Tulosba.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
19.09.2014, 22:27  [ТС] 6
Не помогло. Там два хидера и два *.cpp, я в начале каждого прописал #undef UNICODE, а оно всё равно вместо
FindFirstFile подставляет FindFirstFileW
0
22 / 25 / 11
Регистрация: 10.10.2013
Сообщений: 165
19.09.2014, 22:29 7
kravam, мде... я, к сожалению в вашей среде не работал, деталей не знаю. Ну в крайнем случае вы можете руками прописать FindFirstFileA и будет вам счастье.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
19.09.2014, 22:33  [ТС] 8
Нет. Дело в том, что там кроме этой функции ещё и другие функции есть, везде не перенаписываешься. Кроме того, эти функции принимают аргументы и они все должны соответствовать тык скыть всему и вся. В общем, надо отменить юникод для всего проекта разом.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
19.09.2014, 22:41 9
Стоит попробовать "-U UNICODE" в командной строке компилятора.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
19.09.2014, 22:50  [ТС] 10
Не помогает. Я аж в три места этот параметр прописал.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
19.09.2014, 22:56 11
Цитата Сообщение от kravam Посмотреть сообщение
Не помогает.
Такого просто не может быть.
UNICODE где-то да определен, либо в командной строке компилятора, либо в
подключенных заголовках. В Visual C++ я бы дал команду построить файл с
препроцессинговым выводом и нашел бы там злосчастную строку.
Как это сделать в GCC/MinGw - не в курсе...
1
18842 / 9841 / 2408
Регистрация: 30.01.2014
Сообщений: 17,284
19.09.2014, 23:02 12
Цитата Сообщение от kravam Посмотреть сообщение
Я аж в три места этот параметр прописал.
Потому что -U работает только если макрос до этого тоже был определен в командной строке.
Стоит все-таки поискать файл где unicode выставляется. И что-то подсказывает мне, что это делается внутри библиотеки wx - она может быть так собрана, c этим макросом (что-то вроде wxUSE_UNICODE при сборке библиотеки). Если это действительно так, то категорически не рекомендую локально отключать unicode у себя, чревато нарушением ODR со всеми вытекающими.
1
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
20.09.2014, 21:50  [ТС] 13
Друзья! Я ковырялся-ковырялся с кодом, упрощал его до минимума и вот что получилось:

C++
1
2
3
4
5
6
//poDlg.cpp
#include <wx/wx.h>
void f ()
{
    MessageBox (0, "str", "str", 0);
}
Также я ковырялся с командной строкой, убирал оттуда ненужные параметры (на такой маленький код не нужна первоначальная длинная командная строка) и вот что получил:

Bash
1
E:\wxDev-Cpp\MinGW32\bin\g++.exe -c poDlg.cpp -o poDlg.o -I"E:/wxDev-Cpp/include/common"
Как видим ничё сверхъестественного, кроме последнего параметра, это, наверное, каталог для поиска инклудов.

Компилим, получаем ошибку, из-за который весь сыр-бор разгорелся (первоначально я использовал функцию FindFirstFile, но лучше MessageBox, она попроще будет)

ошибка:
Bash
1
2
3
poDlg.cpp: In function 'void f()':
poDlg.cpp:4:35: error: cannot convert 'const char*' to 'LPCWSTR {aka const wchar_t*}' for argument '
2' to 'int MessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT)'
Дальше я полез в winuser.h где, собсно, прототип MessageBox и увидел, что у меня ОБЯЗАТЕЛЬНО должен быть определён юникод (поскольку вместо MessageBox подставляется MessageBoxW).

И возвращаясь к моему вопросу: где мне ВОТ ТУТ его убрать?

C++
1
2
3
4
5
6
//poDlg.cpp
#include <wx/wx.h>
void f ()
{
    MessageBox (0, "str", "str", 0);
}
Ясне дело, UNICODE определён где-то в дебрях <wx/wx.h>, и я, наверное, могу найти где, на это мне намекнул Убеждённый. Для этого надо получить вывод препроцессора (g++ с параметром -E), я просто этого не сделал ещё, ибо не пойму- ну увижу я, где он определён, а убирать-то его где? В том же самом штатном инклуде, где он и определён?

Но я так работал раньше, а щас хочу цивилизованнно. Повторюсь, не лезть своими толстыми пальцами в штатные инклуды, а изящно где-нибудь в своём аворском файле отменить макрос UNICODE. Неужели не получится?
0
18842 / 9841 / 2408
Регистрация: 30.01.2014
Сообщений: 17,284
20.09.2014, 22:12 14
Цитата Сообщение от kravam Посмотреть сообщение
Ясне дело, UNICODE определён где-то в дебрях <wx/wx.h>, и я, наверное, могу найти где, на это мне намекнул Убеждённый. Для этого надо получить вывод препроцессора (g++ с параметром -E), я просто этого не сделал ещё, ибо не пойму- ну увижу я, где он определён, а убирать-то его где? В том же самом штатном инклуде, где он и определён?
Но я так работал раньше, а щас хочу цивилизованнно. Повторюсь, не лезть своими толстыми пальцами в штатные инклуды, а изящно где-нибудь в своём аворском файле отменить макрос UNICODE. Неужели не получится?
Посмотрел сейчас h-файлы в каталоге wx. Нашел вот что в wx\platform.h:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* set wxUSE_UNICODE to 1 if UNICODE or _UNICODE is defined */
#if defined(_UNICODE) || defined(UNICODE)
#   undef wxUSE_UNICODE
#   define wxUSE_UNICODE 1
#else /* !UNICODE */
#   ifndef wxUSE_UNICODE
#       define wxUSE_UNICODE 0
#   endif
#endif /* UNICODE/!UNICODE */
/* and vice versa: define UNICODE and _UNICODE if wxUSE_UNICODE is 1 */
#if wxUSE_UNICODE
#   ifndef _UNICODE
#       define _UNICODE
#   endif
#   ifndef UNICODE
#       define UNICODE
#   endif
#endif /* wxUSE_UNICODE */
Насчет wxUSE_UNICODE в файле wx/setup_inc.h
C++
1
2
3
4
5
6
7
8
9
10
11
// ----------------------------------------------------------------------------
// Unicode support
// ----------------------------------------------------------------------------
 
// These settings are obsolete: the library is always built in Unicode mode
// now, only set wxUSE_UNICODE to 0 to compile legacy code in ANSI mode if
// absolutely necessary -- updating it is strongly recommended as the ANSI mode
// will disappear completely in future wxWidgets releases.
#ifndef wxUSE_UNICODE
    #define wxUSE_UNICODE 1
#endif
В общем поясню что это значит. Как я уже говорил, библиотека собрана в режиме юникода. Первая цитата из platform.h говорит нам о том, что если библиотека собрана в режиме юникода, то и макрос UNICODE всегда будет выставляется автоматически:
and vice versa: define UNICODE and _UNICODE if wxUSE_UNICODE is 1
За сборку в режиме юникода отвечает макрос wxUSE_UNICODE. Отменить его действие скорее всего не получится (будут ошибки сборки). Но даже если получится, то это почти наверняка приведет к нарушению ODR, что в конечном итоге скажется на стабильности приложения (проще говоря, будет падать).

Выхода я вижу три:
1) Не использовать WinAPI вообще. Вместо этого использовать соответствующие возможности библиотеки wx. Это наиболее правильный способ на мой взгляд.
2) Перекомпилировать (или найти готовую) версию wx в ANSI режиме (без юникода).
3) Использовать функции WinAPI с указанием конкретных версий (W или A).
1
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
20.09.2014, 22:54  [ТС] 15
Цитата Сообщение от DrOffset Посмотреть сообщение
1) Не использовать WinAPI вообще. Вместо этого использовать соответствующие возможности библиотеки wx. Это наиболее правильный способ на мой взгляд.
Так там ни документации, ничё. Какая-то скудная книжонка Programming with wxDev-C++ гуляет по сети, в которой есть такие строки:

Chapter 8- Working With Forms and Dialog
To be written
Да и вообще, почему в библиотеке wx должны быть функции-apiзаменители? Я так понимаю, каждая библиотека отвечает за своё направление. Например, pthread, с которой я знаком за потоки и за ничто более. wx за визуальное программирование. Создал форму, накидал кнопок и будь здоров.

Другое дело, что мне вот тут подумалось, что, наверное, есть всё-таки смысл жёстко вбить юникод в программу создания диалоговое окно, что и было ими сделано.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Значит, можно явно указывать A или W, это да. Значит, тут так- этот способ хорош, если пишешь исходник с ноля. А если берёшь уже готовый код, написанный ранее, где предполагается, что все функции "A", тогда всё плохо. И дело не в том, что вручную всё заменять придётся дело в том, что очень легко пропустить, что именно нужно заменять . Пример. Пишем:

C++
1
2
    WIN32_FIND_DATA FindFileData;
    FindFirstFile("path",&FindFileData);
Компилятор ругается на строчку FindFirstFile. Несколько лёгких пассов руками и имеем:
C++
1
2
    WIN32_FIND_DATA FindFileData;
    FindFirstFileA("path",(LPWIN32_FIND_DATAA)&FindFileData);
Компилятор ошибок не выдаёт. Всё ничё, только этот код работать не будет. А дело в том, что строчку WIN32_FIND_DATA FindFileData; ТОЖЕ НУЖНО ПРАВИТЬ, ибо структура WIN32_FIND_DATA ТОЖЕ В ДВУХ ИПОСТАСЯХ. Но компилятор не ругнулся, а сам я не настолько умный. Всё плохо.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Мне кажется, есть четвёртый хороший способ. Писать сторонний код без юникода и оформлять его в виде функций. А потом просто линковать с юникодовским кодом и всё. Зря что ли придумали раздельную компиляцию?

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0
18842 / 9841 / 2408
Регистрация: 30.01.2014
Сообщений: 17,284
20.09.2014, 23:05 16
Цитата Сообщение от kravam Посмотреть сообщение
Да и вообще, почему в библиотеке wx должны быть функции-apiзаменители? Я так понимаю, каждая библиотека отвечает за своё направление. Например, pthread, с которой я знаком за потоки и за ничто более. wx за визуальное программирование. Создал форму, накидал кнопок и будь здоров.
Это не так в случае wx. Потому что wx - это целый фреймворк, причем кроссплатформенный (как и Qt). Поэтому там и должны быть API заменители, чтобы сделать код переносимым между платформами. Документация там есть. Обрати внимание, что там есть классы и для работы с файлами и для многопоточности и т.п. Также есть книга, не знаю есть ли она на русском. В общем материала достаточно на самом деле.

Так что я буду настаивать, что использовать WinAPI совместно с wx, как ты сказал, нецивилизованно. Это тоже самое, что использовать WinAPI совместно с Qt. Можно, но в очень ограниченных случаях.

Цитата Сообщение от kravam Посмотреть сообщение
Мне кажется, есть четвёртый хороший способ. Писать сторонний код без юникода и оформлять его в виде функций. А потом просто линковать с юникодовским кодом и всё. Зря что ли придумали раздельную компиляцию?
Можно, но это костыль.
0
20.09.2014, 23:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.09.2014, 23:05
Помогаю со студенческими работами здесь

Отменить действие как в блокноте
как мне отменить действие как в блокноте??

Как отменить действие утилиты sysprep?
Использовал эту утилиту для подготовки системы к клонированию и она перестала быть пригодной для...

Как отменить последнее действие в DataGridView1
Как прописать возможность отмены последнего действия в DataGridView1 средствами visual basic net

TabControl как отменить действие CTRL+PageUp
Есть TabControl, который не должен переключать свои вкладки по нажатию клавиш CTRL+PageUp и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru