Вопрос новичка
От: Gosha Украина  
Дата: 10.12.01 20:00
Оценка:
Привет всем!

Вот, начал изучать АТЛ
В качестве примера решил написать простой объект для работы
с файлами, внуть класса которого засунул fopen/fclose/fgets/...
Собрал ДЕБАГ, все нормально работает (подключил в VB, поюзал
без проблем). Начал собирать ReleaseMinDependency выскочила такая
ошибка
Linking...
   Creating library ReleaseMinDependency/atlfiles.lib and object ReleaseMinDependency/atlfiles.exp
LIBCMT.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
ReleaseMinDependency/atlfiles.dll : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

Проект создан АТЛ-евским мастером, подозреваю, что решается все
каким-нибудь дефайном, но, повторюсь, мы сами не местные
Подскажите, плз
Re: Вопрос новичка
От: Igor Soukhov  
Дата: 10.12.01 20:15
Оценка: 3 (1)
Здравствуйте Gosha, Вы писали:

G>Привет всем!


G>Вот, начал изучать АТЛ

G>В качестве примера решил написать простой объект для работы
G>с файлами, внуть класса которого засунул fopen/fclose/fgets/...
G>Собрал ДЕБАГ, все нормально работает (подключил в VB, поюзал
G>без проблем). Начал собирать ReleaseMinDependency выскочила такая
G>ошибка
G>
G>Linking...
G>   Creating library ReleaseMinDependency/atlfiles.lib and object ReleaseMinDependency/atlfiles.exp
G>LIBCMT.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
G>ReleaseMinDependency/atlfiles.dll : fatal error LNK1120: 1 unresolved externals
G>Error executing link.exe.
G>

G>Проект создан АТЛ-евским мастером, подозреваю, что решается все
G>каким-нибудь дефайном, но, повторюсь, мы сами не местные
Gosha — ты знал =) ты знал =) Надо убрать _ATL_MIN_CRT из символов определенных для данного типа билда настроек проека.

G>Подскажите, плз
* thriving in a production environment *
Re[2]: Вопрос новичка
От: Gosha Украина  
Дата: 10.12.01 21:25
Оценка:
Здравствуйте Igor Soukhov, Вы писали:

IS>Здравствуйте Gosha, Вы писали:


G>>Привет всем!


G>>Вот, начал изучать АТЛ

G>>В качестве примера решил написать простой объект для работы
G>>с файлами, внуть класса которого засунул fopen/fclose/fgets/...
G>>Собрал ДЕБАГ, все нормально работает (подключил в VB, поюзал
G>>без проблем). Начал собирать ReleaseMinDependency выскочила такая
G>>ошибка
G>>
G>>Linking...
G>>   Creating library ReleaseMinDependency/atlfiles.lib and object ReleaseMinDependency/atlfiles.exp
G>>LIBCMT.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
G>>ReleaseMinDependency/atlfiles.dll : fatal error LNK1120: 1 unresolved externals
G>>Error executing link.exe.
G>>

G>>Проект создан АТЛ-евским мастером, подозреваю, что решается все
G>>каким-нибудь дефайном, но, повторюсь, мы сами не местные
IS>Gosha — ты знал =) ты знал =) Надо убрать _ATL_MIN_CRT из символов определенных для данного типа билда настроек проека.
Не, не знал но теперь знаю, спасибо.
Боюсь, вопросов будет еще много, ну например:
1. Про какие С-типы данных в АТЛ стоит забыть ?
2. Как добраться (и нужно ли) до VB-ешного Err.Number и Err.Description, я подозреваю, что это частный случай какого-нибудь общего интерфейса ошибок, или нет? Или, как взрослые дяди сообщают об ошибках ?
3. Как создать событие (если привязываться к примеру, например событие типа OnRead в которое передается текущее положение указателя в файле)
4. Как называется та книжка, в которой все это и многое другое описано Желательно на русском языке. Какие-то базовые вещи, что-б велосипеды не клепать.
Re[3]: Вопрос новичка
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.12.01 23:32
Оценка: 6 (2)
Здравствуйте Gosha, Вы писали:

IS>>Gosha — ты знал =) ты знал =) Надо убрать _ATL_MIN_CRT из символов определенных для данного типа билда настроек проека.


Можно так, а можно выбросить fopen/fclose/fgets заменив их на CreateFile/CloseHandl/RedeFile. Удобства это правда не прибавит, если конечно не читать весь файл за раз.

G>Боюсь, вопросов будет еще много, ну например:

G>1. Про какие С-типы данных в АТЛ стоит забыть ?

В смысле чтобы с _ATL_MIN_CRT компилировалось?
Если да, то в про все CRT-ешные (C Run-Time библиотечные) функции и типы. Т.е. вместо strlen -> lstrlen, вместо fopen -> CreateFile...

G>2. Как добраться (и нужно ли) до VB-ешного Err.Number и Err.Description, я подозреваю, что это частный случай какого-нибудь общего интерфейса ошибок, или нет? Или, как взрослые дяди сообщают об ошибках ?


Правильно подозреваешь. Но не случай, а оберкта. Сам интерфейс называестя IErrorInfo (он не один). Подробнее см. в MSDN "Platform SDK->COM->Automation->Error Handling Interfaces".

G>3. Как создать событие (если привязываться к примеру, например событие типа OnRead в которое передается текущее положение указателя в файле)


Проще всего посмотреть примеры (туториалы) от MS (в том же MSDN). Там все довольно понятно.
В двух словах так:
При создании контрола укажи на второй закладке "Suport Connection Points" и "Suport ISuportErrorInfo". В idl-файле найти событийный интерфейс (обычно он начинается с подчеркивания и содержит в себе слово Event). Добавить описание событийных методов. Например:

[id(1)] void OnRead([in] long Pos);

Далее нужно скомпилироваться и после окончания компиляции нажать правую кнопку мыши на имени класса в "Class View". Из выпавшего меню выбрать пункт "Implement Connection Poins".
После этого визард добавит "прокси-вызывалку" для событийного интерфейса. Далее так где нужно вызвать метод пишим Fire_ИмяСобытия(...); и все.

G>4. Как называется та книжка, в которой все это и многое другое описано Желательно на русском языке. Какие-то базовые вещи, что-б велосипеды не клепать.


Лучше просто читать MSDN. Там все есть.
На русском "Модель COM и применение ATL 3.0" Э.Трельсон но автор не асс и перевод поганый.
Так же посмотри ссылки на этом сайте.
Куча примеров применения ATL есть в статьях на этом сайте.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Вопрос новичка
От: Gosha Украина  
Дата: 11.12.01 23:00
Оценка: 4 (1)
Здравствуйте VladD2, Вы писали:

G>>1. Про какие С-типы данных в АТЛ стоит забыть ?


VD>В смысле чтобы с _ATL_MIN_CRT компилировалось?

VD>Если да, то в про все CRT-ешные (C Run-Time библиотечные) функции и типы. Т.е. вместо strlen -> lstrlen, вместо fopen -> CreateFile...
Владислав, спасибо большое за предыдущий ответ, можно Вас еще поспрашивать?
Если можно на примере:
Допустим у меня есть такой метод
[id(3), helpstring("returns some string")] 
HRESULT GetStringValue
    (BSTR SomeString, [out, retval] BSTR stringValue);

(кстати, VB захотелось именно BSTR, это нормально?)
Я хочу в этом методе вернуть переданную мне в первом аргументе строку + "еще что-то". Если бы это был простой char* и char** тип, я бы сделал примерно так:
    ...
    GetStringValue("Some string",&stringValue);
    //stringValue="Some string  and anoter string"
    ...
void GetStringValue(char* SomeString, char** stringValue)
{
    char appendix[]=" and anoter string";
    int result_len=strlen(appendix);
    result_len+=strlen(SomeString);
    result_len++;
    *stringValue=(char*)malloc(result_len);
    memset(*stringValue,0,result_len);
    strcat(*stringValue,SomeString);
    strcat(*stringValue,appendix);
    return;
}

А вот с BSTR я никак не пойму что делать Парился с преобразованием типов и так и этак, то не компилируется, то потом черти что выводит. Владислав, если не трудно, не могли бы Вы подсказать как приведенный выше код на АТЛ выглядит. Я вот тут место даже приготовил
STDMETHODIMP CSomeClass::GetStringValue(BSTR SomeString, BSTR *stringValue)
{

}

Вообще, когда речь идет о методах, возвращающих значения, и свойствах (get_) то указатель на что им передается в качестве аргумента? На пустое место?
Со свойствами (там где строки) SysAllocString() и SysReAllocString это стандартная техника?
VD>Лучше просто читать MSDN. Там все есть.
Я ждал и боялся этого ответа Ну, читать так читать
BSTR как параметр COM-методов
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.12.01 03:04
Оценка: 23 (5) +1 :)
#Имя: FAQ.com.bstr
G>Владислав, спасибо большое за предыдущий ответ, можно Вас еще поспрашивать?

Да, пожалуйста. Причем можно смело на ты.

G>Если можно на примере:

G>Допустим у меня есть такой метод
G>
G>[id(3), helpstring("returns some string")] 
G>HRESULT GetStringValue
G>    (BSTR SomeString, [out, retval] BSTR stringValue);
G>


Сразу можно указать на ошибку и неточность (приводящую к ошибкам).

Сначала ошибка: [out, retval] BSTR stringValue
Когда параметры передаются как "out" или "in,out", то их обязательно нужно описывать как передаваемые по указателю, т.е.: [out, retval] BSTR * pbsValue. При этом память для строкового "out"-параметра должен выделить ты (для "in,out" только если нужно перезанять память выделенную клиентом). Если бы это был параметр простого типа, то занимать ничего не пришлось бы, так как этот буфер должен разместить клиент. Подробнее см. далее.

Теперь неточность... Лучше всегда указывать тип ("in", "out", "in,out") при описании параметров в idl-е. Иначе ты будешь думать что параметр "in", а он может оказаться "in,out". Это может привести к неправильной работе с памятью.

Так что это описание лучше переписать так (то что 1-й параметр "in" я понял из текста приведенного ниже):
HRESULT GetStringValue([in] BSTR SomeString, [out, retval] BSTR * pbsValue);


Префикс у первого параметра я не сделал исходя из соображений, что его имя будет выводится в VB где префикс будет сбивать и путать программиста. Внутри программы лучше их давать.

G>(кстати, VB захотелось именно BSTR, это нормально?)


Да.

G>Я хочу в этом методе вернуть переданную мне в первом аргументе строку + "еще что-то". Если бы это был простой char* и char** тип, я бы сделал примерно так:...

G>А вот с BSTR я никак не пойму что делать Парился с преобразованием типов и так и этак, то не компилируется, то потом черти что выводит. Владислав, если не трудно, не могли бы Вы подсказать как приведенный выше код на АТЛ выглядит. Я вот тут место даже приготовил


Удивительно, но тут описание правильное!

STDMETHODIMP CSomeClass::GetStringValue(BSTR SomeString, BSTR *stringValue)
{
  // Проверяем, что переданный параметр указывает на переменную
  if(!*stringValue)
    return E_POINTER;

  // Создаем переменную-хелпер
  // bs - стандартный префикс для BSTR, а s я использую для указания 
  // того что переменная является смарт-поинтером.
  CComBSTR sbsResult;

  // Конкатенируем к пустой строке первый параметр
  sbsResult.Append(SomeString);

  // Конкатенируем строковый литерал. OLECHAR раскрывается в L или в ничего
  // в зависимости от настроек компиляции (в Win32 всегда в L, но макрос 
  // будет корректнее). 
  sbsResult.Append(OLESTR(" and anoter string"));

  // Отключаем BSTR от хелпера и копируем его в выходной параметр *stringValue
  // Если бы строка sbsResult была бы нам нужна далее, то вместо Dettach нужно 
  // было бы вызвать Copy().
  *stringValue = sbsResult.Dettach();

  // Проверяем что память для строки выделена... паранойя конечно, но...
  if(!*stringValue)
    return E_OUTOFMEMORY;

  return S_OK; // Все в порядке!
}

// ... а теперь вызов...
CComBSTR sbsOut;
HRESULT hr = GetStringValue(CComBSTR(OLESTR("Some string")), &sbsOut);
if(FAILED(hr))
  return hr;
// Используем sbsOut...


Вместо CComBSTR и его метода Append можно вызывать COM-API-шный метод SysAllocStringLen (выделяющий память под BSTR). При этом память из строк нужно копировать как в случае с обыкновенными строками, но нельзя забывать что BSTR имеет (обычно) размер символа 2 байта (sizeof(OLECHAR)). В принципе через API можно написать более быстрый вариант, но коду будет больше, и он будет более опасным, а значит и возможность наделать ошибок будет выше...

G>Вообще, когда речь идет о методах, возвращающих значения, и свойствах (get_) то указатель на что им передается в качестве аргумента? На пустое место?


Указатели в параметрах (вообще это тема большая и не простая, но я дам первое приближение... прошу учесть что мое объяснение не совсем корректно... но для простоты... на первый раз сойдет) должен указывать на размещенный (клиентом) блок памяти. Но BSTR это тоже указатель! Причем "BSTR * " — это так называемый указатель первого уровня, а сам BSTR вложенный. Они управляются разной логикой. Так "BSTR * " должна разместить вызывающая сторона, а сам BSTR занимается вызываемой функцией (для "out"-параметра). "in"-параметры вообще не должны изменяться внутри функции (вернее с их представлением в стеке можно делать что угодно, но с памятью на который они могут указывать ни-ни).

Вот правило для BSTR:

[in] BSTR – память под строку занимает вызывающая сторона. Функция может только читать содержимое строки.
[b][out] BSTR * [/b]- память под строку занимает функция. Вызывающая сторона должна освободить занятую строку.
[in, out] BSTR * - память под строку занимает вызывающая сторона. Функция может освободить занятую память и выделить новую. После возврата управления ответственность за освобождение памяти несет вызывающая сторона.

Память под строку (в любом случае) выделяется с помощью SysAllocStringXxx. Освобождается SysFreeString. Ну, или, как я уже говорил, можно использовать CComBSTR.

G>Со свойствами (там где строки) SysAllocString() и SysReAllocString это стандартная техника?


Да. Но удобнее пользоваться хелпером CComBSTR.

VD>>Лучше просто читать MSDN. Там все есть.

G>Я ждал и боялся этого ответа Ну, читать так читать

Перебарывай страх и научись в нем искать то что нужно. На этом сайте есть хорошая статья как это делать. Найди и прочти.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.