![]() |
|
Модераторы: bsa |
![]()
|
|
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Пишу свой DDE Сервер.
Для этого добавляю головной файл ddeml.h в котором, при компиляции, находится 188 ошибок. Причем ошибки начиная от синтаксических (не там точка с запятой) и до необъявленных идентфикаторов типа HSZ, HCONVLIST и тд. Пишу в VS2008Pro. Так вот вопрос, что я делаю не так и как эти ошибки устранить? |
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 20 Всего: 110 |
ссылку на файл, пожалуйста. и процитируйте ошибки.
|
|||
|
||||
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Сылка на проект
файл с ошибками в прикрепленном файле Присоединённый файл ( Кол-во скачиваний: 6 )
errors.txt 31,60 Kb |
|||
|
||||
| Estranged |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 158 Регистрация: 30.8.2010 Репутация: нет Всего: 3 |
В ddemlsr.cpp перед <windowsx.h> подключить <windows.h> и переставить местами <dde.h> и <ddeml.h> (т.е. dde.h должен быть перед ddeml.h)
В ddemlcl.cpp переставить местами <dde.h> и <ddeml.h> |
|||
|
||||
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
спасибо, разобрался с той проблемой и настигла новая.
Суть в том, что в моем проекте 3 .срр файла, в одном серверная часть, в другом клиентская и в третьем файле мейн функция запускающая сервер и отправляющая\запрашивающая данные и выводящая в консоль. В общем, компилятор стал ругаться на то, что я многократно определил идентификаторы. На самом деле я их все закомментил и все равно ругается.
Где ошибся? Это сообщение отредактировал(а) GremlinProg - 7.9.2011, 06:08 |
|||
|
||||
| Estranged |
|
||||||||||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 158 Регистрация: 30.8.2010 Репутация: нет Всего: 3 |
wallstreet, машина никогда не обманет. Если идентификаторы дублируются, то они дублируются в самом деле.
Вот гарантированно в ddemlsr.cpp есть
и в ddemlsr.cpp есть то же самое:
Ищите лучше. Как все сложно. А в третьем файле main функция запускать должна сервер из первого файла, из второго файла - клиент? В таком случае надо определиться: эти переменные для сервера и клиента общие или у каждого они уникальны. Для этого в С есть специальные ключевые слова, которые в данном случае указывают линкеру, где эта переменная находится: в текущей единице трансляции, где-то в другой единице трансляции. Т.н. спецификаторы класса памяти, коих всего 4, но в данном случае интересны два. Под единицей трансляции понимается результат обработки препроцессором исходного файла. Таким образом, для компилятора эти переменные в разных единицах трансляции не мешают. Когда дело доходит до линкера, он "видит", что один и тот же объект дважды объявлен в разных единицах трансляции. Что должен делать линкер? Объединить их в одну и выделить память под одну переменную и сделать отсылку на один и тот же участок памяти или разделить их по разным участкам памяти. Линкер этого "не знает". И эти ключевые слова static - данная (у нас переменные глобальные) переменная доступна только в текущей единице трансляции extern - данная переменная находится где-то в другой единице трансляции, причем без указания где именно. теперь надо решить вопрос: эти переменные для сервера и клиента общие или у каждого они уникальны? Применить к ним extern или static. например: в ddemlsr.cpp
в ddemlsr.cpp
или же в ddemlsr.cpp
в ddemlsr.cpp
Это сообщение отредактировал(а) GremlinProg - 7.9.2011, 06:12 |
||||||||||||||
|
|||||||||||||||
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
ДДЕСервер
Вроде разобрался с предыдущей проблемой и вот сейчас похоже столкнулся с новой. Нужно получить HINSTANSE моего консольного приложения и делать это гугл мне советует с помощью GetModuleHandle(). Так вот в режиме дебаг заметил что эта функция не возвращает никакого значения. В моем случае hInst = 00000000 Для большей наглядности залил проект. Буду очень благодарен если направите в нужное русло. В очередной раз) |
|||
|
||||
| Estranged |
|
||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 158 Регистрация: 30.8.2010 Репутация: нет Всего: 3 |
Интересно, чем вы руководствовались, когда писали ЭТО:
Функция же принимает входной параметр: 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/dd...v=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 |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Спасибо большое, с этим разобрался.
DDE Server но не могу понять, почему не инициализируется идентификатор канала hConv? что делаю не так? Это сообщение отредактировал(а) wallstreet - 7.9.2011, 23:56 |
|||
|
||||
| Estranged |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 158 Регистрация: 30.8.2010 Репутация: нет Всего: 3 |
Да вроде бы должен инициализироваться.
Тут инициализироваться должен, а потом закрывается соединение.
Где он должен инициализироваться, но не инициализируется? |
|||
|
||||
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
все правильно, просто перед этим сам сервер должен зарегистрировать сервис, топик и айтем в библиотеке DDEML, а при попытке это сделать :
ничего не происходит, т.е. не регистрируется сервис. Т.е. выполняется только клиентская часть, но создать канал не возможно, т.к. нет такого зарегистрированого сервера с аналогичным сервисом. блин я в тупике(( Ссылка на проект Это сообщение отредактировал(а) wallstreet - 8.9.2011, 20:30 |
|||
|
||||
| Estranged |
|
||||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 158 Регистрация: 30.8.2010 Репутация: нет Всего: 3 |
Жаль, тут нет смайлика facepalm...
Сегодня мы познакомимся с кодировкой ASCII. Как известно, печатные символы машина должна как-то отображать на экране в виде, понятном человеку. И ASCII - кодировка для представления арабских цифр, латинского и национального алфавитов (для этого немного дорабатывается сама кодировка), а так же знаков препинания и управляющих символов. Что позволяет невозбранно печатать символы как на экране, так и на принтере времен прошлого века. Образно говоря, это цифровое представление алфавита. тип данных char - character предназначен для хранения строковых данных (если заведен массив) или символов. Этот тип данных хранит ASCII код. Теперь возвращаемся к коду:
Запрос ввести 1 или 2. Мы печатаем на клавиатуре '1' или '2'. Это печатный символ. Операционная система транслирует код нажатой клавиши в соответствующий код ASCII, и программе "кажется", что пользователь нажал '1' или '2'. Код символа помещается по адресу ch где-то в стеке. Обращаемся к таблице кодов и находим, что код символа '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 |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Спасибо за комплексные ответы.
Вы для меня, как, наверное и для всех участников этой ветки, бесценный кладязь информации. С ошибками разобрался, все работает. Единтственно, выводит информацию по серверу вместо: |
|||
|
||||
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Спасибо за комплексные ответы.
Вы для меня, как, наверное, и для всех участников этой ветки бесценный кладязь информации. С ошибками разобрался, все работает. Единтственно, выводит информацию по серверу вместо:
так как показано на рисунке. Кстати если после А.К. поставить штук 50 пробелов, то вот эти ероглифы перестают закрывать остаток надписи. ![]() DDE server Это сообщение отредактировал(а) wallstreet - 12.9.2011, 16:16 |
|||
|
||||
| Estranged |
|
||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 158 Регистрация: 30.8.2010 Репутация: нет Всего: 3 |
В DDEReceive дописать:
В DdeServerCallback заменить третий параметр DdeCreateDataHandle:
|
||||
|
|||||
| wallstreet |
|
||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Спасибо за помощь, теперь все как надо.
Не понимаю почему появляются эти каракули, если при создании области памяти указывается размер буфера
кстати чем функция sizeof() более подходит чем lstrlen(), которая возвращает не кол-во символов в строке, а непосредственно длину без учета '\0'? А еще по возможности прокомментируйте эту строку:
не понимаю как мы к массиву unsigned char прибавляем unsigned long и присваиваем результату '\0'... Фактически замещая иероглифы?!? Пользуясь случаем еще один вопрос хотел бы прояснить для себя. В чем разница между 0 и 0L, если говорим о типе DWORD? Заранее благодарю! Это сообщение отредактировал(а) wallstreet - 13.9.2011, 22:59 |
||||
|
|||||
| Estranged |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 158 Регистрация: 30.8.2010 Репутация: нет Всего: 3 |
Каракули появляются из-за неправильного указания размера буфера. 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, такое тоже бывает. Это сообщение отредактировал(а) Estranged - 14.9.2011, 01:11 |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: нет Всего: 106 |
ужос
-------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: нет Всего: 106 |
-------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Добрый день.
Решил сервер и клиент разбить на два разных приложения и не получается подсоединиться клиентом к серверу, хотя идентификаторы сервиса и топика у них одни и те же. Клиент подвисает на минуту, две и в результате не коннектится. Чувствую, что в какой-то момент нужно приостановить работу сервера и каким-то образом ждать пока клиент не создаст коннект.Только как это сделать не могу понять. Точнее не могу понять на каком этапе и как сервер будет понимать, что к нему пытаются подконнектиться? Обычно это просходит когда колбек сервера возвращает XTYP_CONNECT в котором мы и сравниваем идентификаторы строк сервисов. Но в моем приложении колбек даже не вызывается клиентом. Вобщем опять ай нид хелп.( сервер и клиент прилагаю ниже: сервер клиент Это сообщение отредактировал(а) wallstreet - 22.9.2011, 20:38 |
|||
|
||||
| Estranged |
|
||||||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 158 Регистрация: 30.8.2010 Репутация: нет Всего: 3 |
Названия сервера не совпадает, топик и айтемом тоже не совпадает. Я бы удивился, если бы соединился клиент.
Уберите приведение типа - все станет понятно:
Можно сделать вот так:
Я уже отвечал по поводу этого: http://forum.vingrad.ru/index.php?showtopi...t&p=2398575 Читать с слов "Второе: (LPCWSTR)"hInst" это такая хитрость обойти ошибку C2664 компилятора?"
Сервер не отвечает, потому что он занят:
Мы заблокировали работу программы. Чтобы сервер нам ответил, мы должны предоставить свободу работы для сервера - не блокировать его: В свойствах проекта сервера сменить тип системы на Windows (configuration properties - linker - system) Выглядит вот так. Вместо main написать вот это, только предварительно разберитесь с приведениями типа к LPCWSTR в части с DdeCreateStringHandle:
Среди минусов - невозможно остановить сервер - это приложение без окон. |
||||||||||
|
|||||||||||
| wallstreet |
|
||||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
если открываю сервер так:
выдает ошибку невозможности приобразования const wchar_t[7] в LPSTR. Не заню правильно или нет, но открывая сервер вот так:
при этом строки у меня типа LPSTR, насколько я понимаю это кодировка ASCI, которую в дальнейшем конвертирую в LPWSTR
Вроде ошибок компилятор не выдает, но и консоль не грузится. И чувствую что что-то не так. А так, если отклониться от темы, то купил недавно книгу по Win32 ("Технология программирования на с++ win32 API приложений" Н.А.Литвиненко) в надежде хоть чуток приобрести знаний по типам данных винды, ну и вообще. Вобщем облом, развернутой инфы нет, только вскользь на пол страницы про кодировки юникод и аски в отличии от описания различных функций. Вот реально понимаю, что тема важная, надо знать.. Но как въехать в нее, с чего начать? Столько типов разных, как понимать какой из них применять именно в этом случае ну и вообще.. Вот к примеру в моем примере строки необходимо удалять функцией SysFreeString, однако она принимает только строки типа BSTR, а у меня то LPWSTR... уууу я схожу с ума)) Короче мне опять нужна ваша бесценная помощь. Ссылка на проект Это сообщение отредактировал(а) wallstreet - 25.10.2011, 23:03 |
||||||
|
|||||||
| wallstreet |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 153 Регистрация: 11.8.2011 Репутация: нет Всего: нет |
Господа, ларчик просто открывался))))
Это сообщение отредактировал(а) wallstreet - 17.11.2011, 15:31 |
|||
|
||||
![]()
|
| Правила форума "C/C++: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |