Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибки ddeml.h 
:(
    Опции темы
wallstreet
Дата 2.9.2011, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Пишу свой DDE Сервер.
Для этого добавляю головной файл ddeml.h в котором, при компиляции, находится 188 ошибок.
Причем ошибки начиная от синтаксических (не там точка с запятой) и до необъявленных идентфикаторов типа HSZ, HCONVLIST и тд.
Пишу в VS2008Pro.

Так вот вопрос, что я делаю не так и как эти ошибки устранить?
PM MAIL   Вверх
boostcoder
Дата 2.9.2011, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



ссылку на файл, пожалуйста. и процитируйте ошибки.
PM WWW   Вверх
wallstreet
Дата 2.9.2011, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Сылка на проект

файл с ошибками в прикрепленном файле

Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  errors.txt 31,60 Kb
PM MAIL   Вверх
Estranged
Дата 2.9.2011, 20:17 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 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>
PM MAIL   Вверх
wallstreet
Дата 5.9.2011, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



спасибо, разобрался с той проблемой и настигла новая. 
Суть в том, что в моем проекте 3 .срр файла, в одном серверная часть, в другом клиентская и в третьем файле мейн функция запускающая сервер и отправляющая\запрашивающая данные и выводящая в консоль. В общем, компилятор стал ругаться на то, что я многократно определил идентификаторы.
На самом деле я их все закомментил и все равно ругается.
Цитата

Ошибка    1    error LNK2005: "int (__stdcall* lpDdeProc)(void)" (?lpDdeProc@@3P6GHXZA) уже определен в ddemlcl.obj    ddemlsr.obj
Ошибка    2    error LNK2005: "unsigned long idInst" (?idInst@@3KA) уже определен в ddemlcl.obj    ddemlsr.obj
Ошибка    3    error LNK2005: "struct HSZ__ * hszService" (?hszService@@3PAUHSZ__@@A) уже определен в ddemlcl.obj    ddemlsr.obj
Ошибка    4    error LNK2005: "struct HSZ__ * hszTopic" (?hszTopic@@3PAUHSZ__@@A) уже определен в ddemlcl.obj    ddemlsr.obj
Ошибка    5    error LNK2005: "struct HSZ__ * hszItem" (?hszItem@@3PAUHSZ__@@A) уже определен в ddemlcl.obj    ddemlsr.obj
Ошибка    6    fatal error LNK1169: обнаружен многократно определенный символ - один или более    C:\Users\1\Documents\Visual Studio 2008\Projects\DDEServer\Debug\DDEServer.exe    1

Где ошибся?

Это сообщение отредактировал(а) GremlinProg - 7.9.2011, 06:08
PM MAIL   Вверх
Estranged
Дата 6.9.2011, 00:01 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 30.8.2010

Репутация: нет
Всего: 3



wallstreet, машина никогда не обманет. Если идентификаторы дублируются, то они дублируются в самом деле.

Вот гарантированно в ddemlsr.cpp есть 
Код

FARPROC lpDdeProc;
HSZ hszService = NULL;
HSZ hszTopic = NULL;
HSZ hszItem = NULL;

и в ddemlsr.cpp есть то же самое:
Код

FARPROC lpDdeProc;
HSZ hszService = NULL;
HSZ hszTopic = NULL;
HSZ hszItem = NULL;

Ищите лучше.

Цитата(wallstreet @  5.9.2011,  22:03 Найти цитируемый пост)
Суть в том, что в моем проекте 3 .срр файла, в одном серверная часть, в другом клиентская и в третьем файле мейн функция запускающая сервер и отправляющая\запрашивающая данные и выводящая в консоль.

Как все сложно. А в третьем файле main функция запускать должна сервер из первого файла, из второго файла - клиент?

В таком случае надо определиться:
эти переменные для сервера и клиента общие или у каждого они уникальны.

Для этого в С есть специальные ключевые слова, которые в данном случае указывают линкеру, где эта переменная находится: в текущей единице трансляции, где-то в другой единице трансляции. Т.н. спецификаторы класса памяти, коих всего 4, но в данном случае интересны два.
Под единицей трансляции понимается результат обработки препроцессором исходного файла.
Таким образом, для компилятора эти переменные в разных единицах трансляции не мешают. Когда дело доходит до линкера, он "видит", что один и тот же объект дважды объявлен в разных единицах трансляции. Что должен делать линкер? Объединить их в одну и выделить память под одну переменную и сделать отсылку на один и тот же участок памяти или разделить их по разным участкам памяти. Линкер этого "не знает".

И эти ключевые слова
static - данная (у нас переменные глобальные) переменная доступна только в текущей единице трансляции
extern - данная переменная находится где-то в другой единице трансляции, причем без указания где именно.

теперь надо решить вопрос: эти переменные для сервера и клиента общие или у каждого они уникальны?
Применить к ним extern или static.

например:

в ddemlsr.cpp
Код

FARPROC lpDdeProc;
HSZ hszService = NULL;
HSZ hszTopic = NULL;
HSZ hszItem = NULL;

в ddemlsr.cpp
Код

extern FARPROC lpDdeProc;// это вряд ли, у сервера и клиента разные функции обработки dde
extern HSZ hszService;
extern HSZ hszTopic;
extern HSZ hszItem;

или же
в ddemlsr.cpp
Код

static FARPROC lpDdeProc;
static HSZ hszService;
static HSZ hszTopic;
static HSZ hszItem;

в ddemlsr.cpp
Код

static FARPROC lpDdeProc;
static HSZ hszService;
static HSZ hszTopic;
static HSZ hszItem;


M
GremlinProg
для форматирования текста программного кода пользуйтесь тегами [сode][/сode]!


Это сообщение отредактировал(а) GremlinProg - 7.9.2011, 06:12
PM MAIL   Вверх
wallstreet
Дата 6.9.2011, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



ДДЕСервер

Вроде разобрался с предыдущей проблемой и вот сейчас похоже столкнулся с новой.
Нужно получить HINSTANSE моего консольного приложения и делать это гугл мне советует с помощью
GetModuleHandle(). 
Так вот в режиме дебаг заметил что эта функция не возвращает никакого значения.
В моем случае hInst = 00000000

Для большей наглядности залил проект.
Буду очень благодарен если направите в нужное русло.
В очередной раз)
PM MAIL   Вверх
Estranged
Дата 6.9.2011, 23:51 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 30.8.2010

Репутация: нет
Всего: 3



Интересно, чем вы руководствовались, когда писали ЭТО:
Код

hInst = GetModuleHandle((LPCWSTR)"hInst");


Функция же принимает входной параметр: 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 )

А если очень надо, то получить ее можно вот так:
Код

hInst = GetModuleHandle (NULL);


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

Совершенно невозбранно можно поглядеть адрес загрузки любого модуля, например, ntdll.dll
Код

hInst = GetModuleHandle (TEXT ("ntdll.dll"));

PM MAIL   Вверх
wallstreet
Дата 7.9.2011, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Спасибо большое, с этим разобрался.

DDE Server

но не могу понять, почему не инициализируется идентификатор канала hConv?
что делаю не так?

Это сообщение отредактировал(а) wallstreet - 7.9.2011, 23:56
PM MAIL   Вверх
Estranged
Дата 8.9.2011, 00:17 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 30.8.2010

Репутация: нет
Всего: 3



Да вроде бы должен инициализироваться.

Тут инициализироваться должен, а потом закрывается соединение.
Код

     // Инициализируем DDEML и создаем канал связи
     if(hConv == NULL)
      {
        hConv = DDEClientOpen(hInst,(LPSTR)"BMPServer",(LPSTR)"BMPFile",(LPSTR)"DDEData");


Где он должен инициализироваться, но не инициализируется?
PM MAIL   Вверх
wallstreet
Дата 8.9.2011, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



все правильно, просто перед этим сам сервер должен зарегистрировать сервис, топик и айтем в библиотеке DDEML, а при попытке это сделать :

Код

DDEServerOpen(hInst,(LPSTR)"BMPServer",(LPSTR)"BMPFile",(LPSTR)"DDEData");


ничего не происходит, т.е. не регистрируется сервис. Т.е. выполняется только клиентская часть, но создать канал не возможно, т.к. нет такого зарегистрированого сервера с аналогичным сервисом.

блин я в тупике((

Ссылка на проект

Это сообщение отредактировал(а) wallstreet - 8.9.2011, 20:30
PM MAIL   Вверх
Estranged
Дата 9.9.2011, 00:45 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 30.8.2010

Репутация: нет
Всего: 3



Жаль, тут нет смайлика facepalm...

Сегодня мы познакомимся с кодировкой ASCII. Как известно, печатные символы машина должна как-то отображать на экране в виде, понятном человеку. 
И ASCII - кодировка для представления арабских цифр, латинского и национального алфавитов (для этого немного дорабатывается сама кодировка), а так же знаков препинания и управляющих символов. Что позволяет невозбранно печатать символы как на экране, так и на принтере времен прошлого века.
Образно говоря, это цифровое представление алфавита.

тип данных char - character предназначен для хранения строковых данных (если заведен массив) или символов. Этот тип данных хранит ASCII код.

Теперь возвращаемся к коду:
Код

    char ch;
    hInst = GetModuleHandle(NULL);
    cout << "Start the server? (1 - yes|| 2 - no): ";
    cin >> ch;
    switch(ch)
    {
    case 1:
        {
            DDEServerOpen(hInst, (LPSTR)"BMPServer", (LPSTR)"BMPFile", (LPSTR)"DDEData");
        }
    case 2:
        {
            // Завершаем работу с DDEML
            DDEServerClose();
        }
    }


Запрос ввести 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':

Перевести код символа цифры в саму цифру:
Код

switch(ch - '0') // или же ch - 48, что делать вообще-то можно, но будут бить по рукам
case 1:
...
case 2:
...


или же сравнить код с кодом цифры
Код

switch(ch)
case '1':// одинарные кавычки
...
case '2':
...


И в-третьих:
после case потерян break?

Код

    switch(ch)
    {
    case '1':
        {
            ;
        }
        break;
    case '2':
        {
            ;
        }
        break;
    }


Потому что если выбрать 1, то выполнится ветка 1 и ветка 2, а судя по сообщению "Start the server? (1 - yes|| 2 - no): " такое не планировалось явно: создать сервер и тут же его закрыть. Хотя я могу ошибаться.
PM MAIL   Вверх
wallstreet
Дата 12.9.2011, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Спасибо за комплексные ответы.
Вы для меня, как, наверное и для всех участников этой ветки, бесценный кладязь информации.

С ошибками разобрался, все работает.
Единтственно, выводит информацию по серверу вместо:
PM MAIL   Вверх
wallstreet
Дата 12.9.2011, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.8.2011

Репутация: нет
Всего: нет



Спасибо за комплексные ответы.
Вы для меня, как, наверное, и для всех участников этой ветки бесценный кладязь информации.

С ошибками разобрался, все работает.
Единтственно, выводит информацию по серверу вместо:

Цитата

"DDEML Server v.1.0, © Gursky A.K.";


так как показано на рисунке. Кстати если после А.К. поставить штук 50 пробелов, то вот эти ероглифы перестают закрывать остаток надписи.

user posted image


DDE server

Это сообщение отредактировал(а) wallstreet - 12.9.2011, 16:16
PM MAIL   Вверх
Estranged
Дата 12.9.2011, 22:47 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 30.8.2010

Репутация: нет
Всего: 3



В DDEReceive дописать:
Код

    // Получаем строку от сервера 
    if(hData != NULL)
    {
      DWORD dwGetBytes = DdeGetData(hData, (LPBYTE)szBuf, nBufSize, 0L);
      *(LPSTR)(((LPBYTE)szBuf) + dwGetBytes) = '\0';


В DdeServerCallback заменить третий параметр DdeCreateDataHandle:
Код

hData = DdeCreateDataHandle(idInst, (LPBYTE)szDDEServerVersion, sizeof (szDDEServerVersion), 0, hszItem, CF_TEXT, 0);

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1372 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.