| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Ошибки ddeml.h |
| Автор: wallstreet 2.9.2011, 16:41 |
| Пишу свой DDE Сервер. Для этого добавляю головной файл ddeml.h в котором, при компиляции, находится 188 ошибок. Причем ошибки начиная от синтаксических (не там точка с запятой) и до необъявленных идентфикаторов типа HSZ, HCONVLIST и тд. Пишу в VS2008Pro. Так вот вопрос, что я делаю не так и как эти ошибки устранить? |
| Автор: boostcoder 2.9.2011, 17:08 |
| ссылку на файл, пожалуйста. и процитируйте ошибки. |
| Автор: wallstreet 2.9.2011, 17:36 |
| http://zalil.ru/31640260 файл с ошибками в прикрепленном файле |
| Автор: Estranged 2.9.2011, 20:17 |
| В ddemlsr.cpp перед <windowsx.h> подключить <windows.h> и переставить местами <dde.h> и <ddeml.h> (т.е. dde.h должен быть перед ddeml.h) В ddemlcl.cpp переставить местами <dde.h> и <ddeml.h> |
| Автор: wallstreet 5.9.2011, 22:03 | ||
| спасибо, разобрался с той проблемой и настигла новая. Суть в том, что в моем проекте 3 .срр файла, в одном серверная часть, в другом клиентская и в третьем файле мейн функция запускающая сервер и отправляющая\запрашивающая данные и выводящая в консоль. В общем, компилятор стал ругаться на то, что я многократно определил идентификаторы. На самом деле я их все закомментил и все равно ругается.
Где ошибся? |
| Автор: wallstreet 6.9.2011, 17:11 |
| http://zalil.ru/31657419 Вроде разобрался с предыдущей проблемой и вот сейчас похоже столкнулся с новой. Нужно получить HINSTANSE моего консольного приложения и делать это гугл мне советует с помощью GetModuleHandle(). Так вот в режиме дебаг заметил что эта функция не возвращает никакого значения. В моем случае hInst = 00000000 Для большей наглядности залил проект. Буду очень благодарен если направите в нужное русло. В очередной раз) |
| Автор: Estranged 6.9.2011, 23:51 | ||||||
Интересно, чем вы руководствовались, когда писали ЭТО:
Функция же принимает входной параметр: The name of the loaded module (either a .dll or .exe file) hInst - это модуль такой есть? Сомневаюсь все же. Второе: (LPCWSTR)"hInst" это такая хитрость обойти ошибку C2664 компилятора? Не могу привести тип 'const char [6]' к 'LPCWSTR'? Для этого специально заведена константа L. LPCWSTR - long ponter to const wide string. Потому что проект собирается с использованием UNICODE набора символов. Для этого требуется строку привести к этому UNICODE: L"hInst". Что само по себе плохо. Потому что если сменить набор символов на т.н. multi-byte character set, то программа перестанет компилироваться, т.к. L уже не нужна. Для обхода этого ограничения придумали макрос: TEXT (a) - http://msdn.microsoft.com/en-us/library/dd374074%28v=vs.85%29.aspx можно использовать _T(a) например: TEXT("hInst"); Поэтому следует написать: GetModuleHandle (TEXT ("hInst")); Но даже в этом случае функция вернет NULL. (Впрочем, непонятно, зачем понадобилась эта самая HINSTANSE hInst, ведь она нигде не используется, это так, по-секрету. Если все же думаете, что MakeProcInstance для чего-то использует hInst, то это заблуждение. Теперь этот макрос устарел и не должен применяться. Это наследие Win16, в Win32 такое применять не нужно. См. http://msdn.microsoft.com/en-us/site/aa383722 ) А если очень надо, то получить ее можно вот так:
Скажу по-секрету, что это на самом деле ни что иное, как виртуальный адрес, куда загружен исполняемый модуль процесса, который вызвал эту функцию с таким параметром. Даже если вызвал не главный поток в какой-либо dll а не в самом исполняемом модуле процесса. Совершенно невозбранно можно поглядеть адрес загрузки любого модуля, например, ntdll.dll
|
| Автор: wallstreet 7.9.2011, 18:19 |
| Спасибо большое, с этим разобрался. http://zalil.ru/31665059 но не могу понять, почему не инициализируется идентификатор канала hConv? что делаю не так? |
| Автор: Estranged 8.9.2011, 00:17 | ||
| Да вроде бы должен инициализироваться. Тут инициализироваться должен, а потом закрывается соединение.
Где он должен инициализироваться, но не инициализируется? |
| Автор: wallstreet 8.9.2011, 11:35 | ||
все правильно, просто перед этим сам сервер должен зарегистрировать сервис, топик и айтем в библиотеке DDEML, а при попытке это сделать :
ничего не происходит, т.е. не регистрируется сервис. Т.е. выполняется только клиентская часть, но создать канал не возможно, т.к. нет такого зарегистрированого сервера с аналогичным сервисом. блин я в тупике(( http://zalil.ru/31669248 |
| Автор: Estranged 9.9.2011, 00:45 | ||||||||
| Жаль, тут нет смайлика facepalm... Сегодня мы познакомимся с кодировкой ASCII. Как известно, печатные символы машина должна как-то отображать на экране в виде, понятном человеку. И ASCII - кодировка для представления арабских цифр, латинского и национального алфавитов (для этого немного дорабатывается сама кодировка), а так же знаков препинания и управляющих символов. Что позволяет невозбранно печатать символы как на экране, так и на принтере времен прошлого века. Образно говоря, это цифровое представление алфавита. тип данных char - character предназначен для хранения строковых данных (если заведен массив) или символов. Этот тип данных хранит ASCII код. Теперь возвращаемся к коду:
Запрос ввести 1 или 2. Мы печатаем на клавиатуре '1' или '2'. Это печатный символ. Операционная система транслирует код нажатой клавиши в соответствующий код ASCII, и программе "кажется", что пользователь нажал '1' или '2'. Код символа помещается по адресу ch где-то в стеке. Обращаемся к http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters и находим, что код символа '1' есть число 49, а код '2' - 50. Поэтому по адресу ch находится число 49 или 50. Далее мы переходим к ветвлению, которое, кажется, все же неправильно написано. сравнить 49 (50) с 1 или 2. Совпадений нет. Поэтому программа сразу же завершает свое выполнение. Т.е. мы пытаемся сравнить код символа '1' с самим числом 1. Что же делать? Как говорят физики: переведите все в систему СИ, тонны перевести в килограммы и т.п. Для этого можно вычесть из ch код символа 0, который равен 48 или же сравнивать ch с кодами символов '1' и '2': Перевести код символа цифры в саму цифру:
или же сравнить код с кодом цифры
И в-третьих: после case потерян break?
Потому что если выбрать 1, то выполнится ветка 1 и ветка 2, а судя по сообщению "Start the server? (1 - yes|| 2 - no): " такое не планировалось явно: создать сервер и тут же его закрыть. Хотя я могу ошибаться. |
| Автор: wallstreet 12.9.2011, 15:53 |
| Спасибо за комплексные ответы. Вы для меня, как, наверное и для всех участников этой ветки, бесценный кладязь информации. С ошибками разобрался, все работает. Единтственно, выводит информацию по серверу вместо: |
| Автор: wallstreet 12.9.2011, 15:53 | ||
| Спасибо за комплексные ответы. Вы для меня, как, наверное, и для всех участников этой ветки бесценный кладязь информации. С ошибками разобрался, все работает. Единтственно, выводит информацию по серверу вместо:
так как показано на рисунке. Кстати если после А.К. поставить штук 50 пробелов, то вот эти ероглифы перестают закрывать остаток надписи. ![]() http://zalil.ru/31686795 |
| Автор: Estranged 12.9.2011, 22:47 | ||||
В DDEReceive дописать:
В DdeServerCallback заменить третий параметр DdeCreateDataHandle:
|
| Автор: wallstreet 13.9.2011, 22:41 | ||||
| Спасибо за помощь, теперь все как надо. Не понимаю почему появляются эти каракули, если при создании области памяти указывается размер буфера
кстати чем функция sizeof() более подходит чем lstrlen(), которая возвращает не кол-во символов в строке, а непосредственно длину без учета '\0'? А еще по возможности прокомментируйте эту строку:
не понимаю как мы к массиву unsigned char прибавляем unsigned long и присваиваем результату '\0'... Фактически замещая иероглифы?!? Пользуясь случаем еще один вопрос хотел бы прояснить для себя. В чем разница между 0 и 0L, если говорим о типе DWORD? Заранее благодарю! |
| Автор: Estranged 14.9.2011, 01:09 | ||
Каракули появляются из-за неправильного указания размера буфера. DdeCreateDataHandle требует размер буфера в байтах, lstrlen же в данном случае требует UNICODE строку, коей szDDEServerVersion не является, поэтому надо использовать lstrlenA, но нет смысла это делать, потому что строка szDDEServerVersion не изменяется нигде, отчего можно использовать sizeof, который будет вычислен в процессе компиляции, а не во время работы программы. Конечно, если длина строки заранее неизвестна, то надо использовать lstrlenA (строка) + 1, в данном случае просто совпадение, что длина строки равна ее размеру в байтах, для UNICODE такой финт не проходит, поэтому универсальный способ - умножить размер строки на размер одного символа строки ((lstrlen () + 1) * sizeof (TCHAR)), для UNICODE это будет равносильно умножению на два, а для однобайтовых символов - на 1. Эта строка записывает нуль-терминатор после последнего актуального символа, полученного в функции DdeGetData, эта строка не нужна здесь, если есть учет нуль-терминатора в DdeCreateDataHandle. И не замещает иероглифы, а устанавливает окончание строки. Все строки оканчиваются специальным непечатным символом - нуль-терминатором. Вообще-то, это арифметика указателей, просто найти адрес по смещению dwGetBytes байт от начала szBuf и вписать туда нуль-терминатор. DWORD - double word. Word - 16-битное число. В данном случае, это 32-битное беззнаковое целое число (unsigned long). А посфикс L в числе - это просто указание, что данная константа типа long. Формально в этом проекте разницы нет никакой, т.к. в модели данных (компилятор MSVS C/C++) размеры в байтах типа int и long совпадают, разница есть тогда, когда long больше по размеру, чем int, такое тоже бывает. |
| Автор: GremlinProg 14.9.2011, 05:53 | ||
ужос
|
| Автор: GremlinProg 16.9.2011, 10:12 | ||
|
| Автор: wallstreet 22.9.2011, 20:35 |
| Добрый день. Решил сервер и клиент разбить на два разных приложения и не получается подсоединиться клиентом к серверу, хотя идентификаторы сервиса и топика у них одни и те же. Клиент подвисает на минуту, две и в результате не коннектится. Чувствую, что в какой-то момент нужно приостановить работу сервера и каким-то образом ждать пока клиент не создаст коннект.Только как это сделать не могу понять. Точнее не могу понять на каком этапе и как сервер будет понимать, что к нему пытаются подконнектиться? Обычно это просходит когда колбек сервера возвращает XTYP_CONNECT в котором мы и сравниваем идентификаторы строк сервисов. Но в моем приложении колбек даже не вызывается клиентом. Вобщем опять ай нид хелп.( сервер и клиент прилагаю ниже: http://zalil.ru/31743691 http://zalil.ru/31743805 |
| Автор: Estranged 23.9.2011, 23:56 | ||||||||||
| Названия сервера не совпадает, топик и айтемом тоже не совпадает. Я бы удивился, если бы соединился клиент. Уберите приведение типа - все станет понятно:
Можно сделать вот так:
Я уже отвечал по поводу этого: http://forum.vingrad.ru/index.php?showtopic=337356&view=findpost&p=2398575 Читать с слов "Второе: (LPCWSTR)"hInst" это такая хитрость обойти ошибку C2664 компилятора?"
Сервер не отвечает, потому что он занят:
Мы заблокировали работу программы. Чтобы сервер нам ответил, мы должны предоставить свободу работы для сервера - не блокировать его: В свойствах проекта сервера сменить тип системы на Windows (configuration properties - linker - system) Выглядит вот http://www.etechplanet.com/image.axd?picture=3c18edd0-4aba-4822-83c2-ee20262ab9c9_9.png. Вместо main написать вот это, только предварительно разберитесь с приведениями типа к LPCWSTR в части с DdeCreateStringHandle:
Среди минусов - невозможно остановить сервер - это приложение без окон. |
| Автор: wallstreet 25.10.2011, 19:03 | ||||||
если открываю сервер так:
выдает ошибку невозможности приобразования const wchar_t[7] в LPSTR. Не заню правильно или нет, но открывая сервер вот так:
при этом строки у меня типа LPSTR, насколько я понимаю это кодировка ASCI, которую в дальнейшем конвертирую в LPWSTR
Вроде ошибок компилятор не выдает, но и консоль не грузится. И чувствую что что-то не так. А так, если отклониться от темы, то купил недавно книгу по Win32 ("Технология программирования на с++ win32 API приложений" Н.А.Литвиненко) в надежде хоть чуток приобрести знаний по типам данных винды, ну и вообще. Вобщем облом, развернутой инфы нет, только вскользь на пол страницы про кодировки юникод и аски в отличии от описания различных функций. Вот реально понимаю, что тема важная, надо знать.. Но как въехать в нее, с чего начать? Столько типов разных, как понимать какой из них применять именно в этом случае ну и вообще.. Вот к примеру в моем примере строки необходимо удалять функцией SysFreeString, однако она принимает только строки типа BSTR, а у меня то LPWSTR... уууу я схожу с ума)) Короче мне опять нужна ваша бесценная помощь. http://zalil.ru/31933097 |
| Автор: wallstreet 17.11.2011, 15:28 | ||
Господа, ларчик просто открывался))))
|