Мне, также как и вам, много приходится работать с Interop, :-) поэтому добавлю свои пять копеек:
1) есть возможность не добавлять сборку в GAC для ComExport. Для этого при регистрации сборки через regasm.exe нужно указать ключи /codebase /tlb — этого будет достаточно.
Для релизов так делать не очень красиво, но для отладки или тестирования RC вполне можно. Ну или в случае, если referenced сборки не являются strong named.
2) однажды столкнулись со случаем, когда в Excel не получалось обратиться из VBA к COM-компоненту, написанному на C# (.NET 2.0). Выяснилось, что Excel использовал среду исполнения .NET 1.1, хотя в системе был весь набор фреймворков — от 1.1 до 3.5. Вылечилось установкой VSTO Runtime (хотя само VSTO не использовали).
Зато (в других наших проектах) без проблем получается использовать в новых фреймворках компоненты, написанные под 1.1. Доходит до курьёза: основное приложение написано на .NET CF 3.5, оно использует компоненту на .NET CF 2.0, а та юзает логгирование через log4net (.NET CF 1.1). И всё работает. :-)
Помогите с многоточием, пожалуйста.
После восклицательного и вопросительного знаков ставить символ «…» нельзя, будет слишком много точек, а ставить просто две точки тоже не хочется — это собьёт всю красоту типографики.
Как быть?.. :-)
Если нужны такие фишки, которые в C++ выглядят оверхедом — советую обратить внимание на C# и Java. В них отражение, упаковка (и прочие фантастические для C++ вещи) — просто неотъемлимая часть среды и языка. И отлаживать их значительно проще, и ошибки уже другого уровня, не GPF при чтении неправильного указателя, а просто исключения.
Однако, холивара не будет, потому что C++ и C# — действительно разные языки, у каждого своя ниша.
И поведение компилятора, который подставляет значение 10, вполне легко объяснить.
При переопределении виртуальной функции всё, что меняет потомок в родителе — это адрес функции, хранящийся в области памяти экземпляра. Никакой дополнительной информации больше потомок туда не вкладывает (ну разве что если не включен RTTI или прочие навороты для позднего связывания).
Поэтому компилятор и не может на основе просто указателя на базовый тип A взять такую информацию, как значение параметра по умолчанию.
С другой стороны, количество параметров при вызове функции всегда должно быть постоянным и должно соответствовать сигнатуре функции, поэтому при каждом вызове компилятор должен положить в стек столько чисел, сколько аргументов у функции.
Более того, совершать догадки вроде «Да тут же присвоен указатель на дочерний класс B! Дай-ка я другое значение по умолчанию подставлю» компилятору категорически нельзя делать! Ведь поведение строки
A * pa = new B();
не должно зависеть от правого выражения и, по логике, должно быть идентичным поведению такой строки:
A * pa = GetSomeAChild();
где GetSomeAChild — функция, возвращающая указатель типа A*, а уж какой на самом деле там тип возвращён — A, B или другой их потомок с ещё одним значением параметра по умолчанию — никто не знает.
Отсюда и вполне логичное требование в документации руководствоваться типом указателя.
P.S. Кстати, в C# 3.0 от правого выражения действительно может зависеть тип переменной, если описывать её как
var ds = new DataSet();
Но это C#, в нём упрощается код и усложняется среда исполнения и компилятор, а в C++, наоборот, простое исполнение при сложном коде.
Автор, спасибо! Ваша статья помогла мне осознать, что у меня, на самом деле, в жизни нет цели. А раз нет цели — то и нет критерия успешности, критерия удовлетворённости жизнью.
Есть простой способ добавить в свою программу поддержку макросов или функций — через Microsoft.CSharp.CSharpCodeProvider. Компилирование выражения, функции или класса через этот класс занимает десяток строк, а в итоге получается готовая сборка. Плюсы очевидны: простота; надёжность компилятора (используется тот же, что и в csc.exe); результат является не интерпретируемым, а исполняемым (офигенный бонус в скорости).
В атрибуте DllImport есть параметр SetLastError. Пример из MSDN:
[DllImport(«user32.dll», SetLastError=true)]
public static extern int MessageBoxA(int hWnd, String text, String caption, uint type);
После вызова функции маршаллер вызовет winapi-функцию GetLastError и сохранит возвращённое значение. Потом его можно будет получить через Marshal.GetLastWin32Error.
MSDN говорит, что значение по умолчанию — false. Возможно, если оно false, то GetLastWin32Error будет не возвращать сохранённое значение, а вызывать GetLastError непосредственно.
От блин! Забыл, что бэкапы пакую Rar-ом в режиме Fast…
Ну а в наилучшем сжатии Rar добился результата в 55 мегов.
Так что в топку пока этот 7-Zip… Пока не появится способ нормально задавать степень сжатия через командную строку (или пока не появится внятная документация на текущий способ) — им пользоваться будет нецелесообразно.
Кстати, в справке английский язык очень плохой. :-( Pure Russian, как говорится.
Подскажите, пожалуйста.
Гуёвой версией запаковал бэкап (351 мег; 93 мега в раре) и получил 63 мега. Параметры: PPMd, Ultra, 512М. Вроде результат хороший, можно переделывать батник на 7z. Но никак не могу воспроизвести эти настройки в консольной версии. Лучший результат — 70 мегабайт — получил с помощью -t7z -m0=PPMd:mem=512m:o=16
Подскажите, как подобрать параметры командной строки?
(help.chm зачитал до дыр, лучше не стало)
Вот! Наконец-то хоть кто-то это произнёс вслух! :-)
Для сжатия текстовых данных и 7z, и WinRar используют алгоритм PPM (или PPMII), и думаю, что не совру, если скажу, что 95% всех современных архиваторов взяли реализацию этого алгоритма из PPMd Дмитрия Шкарина. А она уже в PPMd хороша настолько, что улучшить там почти нечего.
Поэтому на текстах разницы быть не должно, у 7z вряд ли набор предпроцессоров богаче WinRar-овского.
Так вот… Автору топика большая просьба перепроверить ещё раз на свежих версиях программ и показать все настройки сжатия. А ещё лучше — дать возможность нам самим это перепроверить.
Ведь не зря сравнительные тесты архиваторов уже лет 10 проводятся на одних и тех же наборах файлов, самым популярным из которых является Calgary Corpus.
Объективность и возможность проверки — вот главные критерии сабжа и блога. Разве не так? :-)
Дааа… С премиями в IT-сфере приходится сталкиваться редко, увы.
Да и отпуск сложно назвать отпуском, если тебя каждое утро будят звонками на тему «где мой файл», «у нас интернет не работает» и проч. и проч…
Похоже, каждый увидел в этом графике что-то своё, знакомое… :-)
Не ругайте сильно человека, он только на первом курсе и прошёл только «Типы и структуры данных», а ассемблер у него будет на втором курсе. :-)
У Аркадия и Бориса Стругацких есть замечательная цитата:
Ubi nihil vales, ibi nihil velis (где ты ни на что не способен, там ты не должен ничего хотеть).
Поэтому нет нужды с такой агрессивностью бросаться переводить стрелки на Microsoft (якобы они недосмотрели), когда не понимаешь, о чём идёт речь.
А имя Георгия Хазана я встречал ещё шесть лет назад в проекте Fidolook… До сих пор пользуюсь этим проектом, подтягивающим привычный ОЕ 6.0 до нормального уровня и добавляющим в него кучу фидошных вкусностей.
Мне очень нравятся корпусные кулеры GlaciaTech (точное название модели не помню) на 80, 90 и 120 мм. Благодаря «правильной» форме крыльчатки они работают довольно тихо при очень хорошем потоке воздуха (сильном и не расходящимся конусом).
Совершенно верно.
Отмечу только, что обработчик события CancelKeyPress выполняется в другом потоке, поэтому использование в нём несинхронизированных Console.WriteLine может перемешать вывод основного потока и нашего обработчика, а Console.ReadLine вообще может выкинуть исключение, был как-то такой случай.
Мне, также как и вам, много приходится работать с Interop, :-) поэтому добавлю свои пять копеек:
1) есть возможность не добавлять сборку в GAC для ComExport. Для этого при регистрации сборки через regasm.exe нужно указать ключи /codebase /tlb — этого будет достаточно.
Для релизов так делать не очень красиво, но для отладки или тестирования RC вполне можно. Ну или в случае, если referenced сборки не являются strong named.
2) однажды столкнулись со случаем, когда в Excel не получалось обратиться из VBA к COM-компоненту, написанному на C# (.NET 2.0). Выяснилось, что Excel использовал среду исполнения .NET 1.1, хотя в системе был весь набор фреймворков — от 1.1 до 3.5. Вылечилось установкой VSTO Runtime (хотя само VSTO не использовали).
Зато (в других наших проектах) без проблем получается использовать в новых фреймворках компоненты, написанные под 1.1. Доходит до курьёза: основное приложение написано на .NET CF 3.5, оно использует компоненту на .NET CF 2.0, а та юзает логгирование через log4net (.NET CF 1.1). И всё работает. :-)
После восклицательного и вопросительного знаков ставить символ «…» нельзя, будет слишком много точек, а ставить просто две точки тоже не хочется — это собьёт всю красоту типографики.
Как быть?.. :-)
(a.*((void(A::*)(void))&A::x))();
Указатель на функцию-член класса. Компилируется и работает в VS2008, на других компиляторах не пробовал.
Знаете… Если я был бы компилятором — я бы сошёл с ума, разбирая это выражение. :-)
Если нужны такие фишки, которые в C++ выглядят оверхедом — советую обратить внимание на C# и Java. В них отражение, упаковка (и прочие фантастические для C++ вещи) — просто неотъемлимая часть среды и языка. И отлаживать их значительно проще, и ошибки уже другого уровня, не GPF при чтении неправильного указателя, а просто исключения.
Однако, холивара не будет, потому что C++ и C# — действительно разные языки, у каждого своя ниша.
И поведение компилятора, который подставляет значение 10, вполне легко объяснить.
При переопределении виртуальной функции всё, что меняет потомок в родителе — это адрес функции, хранящийся в области памяти экземпляра. Никакой дополнительной информации больше потомок туда не вкладывает (ну разве что если не включен RTTI или прочие навороты для позднего связывания).
Поэтому компилятор и не может на основе просто указателя на базовый тип A взять такую информацию, как значение параметра по умолчанию.
С другой стороны, количество параметров при вызове функции всегда должно быть постоянным и должно соответствовать сигнатуре функции, поэтому при каждом вызове компилятор должен положить в стек столько чисел, сколько аргументов у функции.
Более того, совершать догадки вроде «Да тут же присвоен указатель на дочерний класс B! Дай-ка я другое значение по умолчанию подставлю» компилятору категорически нельзя делать! Ведь поведение строки
A * pa = new B();
не должно зависеть от правого выражения и, по логике, должно быть идентичным поведению такой строки:
A * pa = GetSomeAChild();
где GetSomeAChild — функция, возвращающая указатель типа A*, а уж какой на самом деле там тип возвращён — A, B или другой их потомок с ещё одним значением параметра по умолчанию — никто не знает.
Отсюда и вполне логичное требование в документации руководствоваться типом указателя.
P.S. Кстати, в C# 3.0 от правого выражения действительно может зависеть тип переменной, если описывать её как
var ds = new DataSet();
Но это C#, в нём упрощается код и усложняется среда исполнения и компилятор, а в C++, наоборот, простое исполнение при сложном коде.
Спасибо ещё раз! Я понял, куда надо стремиться.
[DllImport(«user32.dll», SetLastError=true)]
public static extern int MessageBoxA(int hWnd, String text, String caption, uint type);
После вызова функции маршаллер вызовет winapi-функцию GetLastError и сохранит возвращённое значение. Потом его можно будет получить через Marshal.GetLastWin32Error.
MSDN говорит, что значение по умолчанию — false. Возможно, если оно false, то GetLastWin32Error будет не возвращать сохранённое значение, а вызывать GetLastError непосредственно.
Ну а в наилучшем сжатии Rar добился результата в 55 мегов.
Так что в топку пока этот 7-Zip… Пока не появится способ нормально задавать степень сжатия через командную строку (или пока не появится внятная документация на текущий способ) — им пользоваться будет нецелесообразно.
Кстати, в справке английский язык очень плохой. :-( Pure Russian, как говорится.
Гуёвой версией запаковал бэкап (351 мег; 93 мега в раре) и получил 63 мега. Параметры: PPMd, Ultra, 512М. Вроде результат хороший, можно переделывать батник на 7z. Но никак не могу воспроизвести эти настройки в консольной версии. Лучший результат — 70 мегабайт — получил с помощью -t7z -m0=PPMd:mem=512m:o=16
Подскажите, как подобрать параметры командной строки?
(help.chm зачитал до дыр, лучше не стало)
Для сжатия текстовых данных и 7z, и WinRar используют алгоритм PPM (или PPMII), и думаю, что не совру, если скажу, что 95% всех современных архиваторов взяли реализацию этого алгоритма из PPMd Дмитрия Шкарина. А она уже в PPMd хороша настолько, что улучшить там почти нечего.
Поэтому на текстах разницы быть не должно, у 7z вряд ли набор предпроцессоров богаче WinRar-овского.
Так вот… Автору топика большая просьба перепроверить ещё раз на свежих версиях программ и показать все настройки сжатия. А ещё лучше — дать возможность нам самим это перепроверить.
Ведь не зря сравнительные тесты архиваторов уже лет 10 проводятся на одних и тех же наборах файлов, самым популярным из которых является Calgary Corpus.
Объективность и возможность проверки — вот главные критерии сабжа и блога. Разве не так? :-)
Похоже, идею о том, что «мало быть талантливым работником, но надо ещё и уметь преподнести себя», нужно усваивать как можно раньше.
Да и отпуск сложно назвать отпуском, если тебя каждое утро будят звонками на тему «где мой файл», «у нас интернет не работает» и проч. и проч…
Похоже, каждый увидел в этом графике что-то своё, знакомое… :-)
У Аркадия и Бориса Стругацких есть замечательная цитата:
Ubi nihil vales, ibi nihil velis (где ты ни на что не способен, там ты не должен ничего хотеть).
Поэтому нет нужды с такой агрессивностью бросаться переводить стрелки на Microsoft (якобы они недосмотрели), когда не понимаешь, о чём идёт речь.
А имя Георгия Хазана я встречал ещё шесть лет назад в проекте Fidolook… До сих пор пользуюсь этим проектом, подтягивающим привычный ОЕ 6.0 до нормального уровня и добавляющим в него кучу фидошных вкусностей.
Отмечу только, что обработчик события CancelKeyPress выполняется в другом потоке, поэтому использование в нём несинхронизированных Console.WriteLine может перемешать вывод основного потока и нашего обработчика, а Console.ReadLine вообще может выкинуть исключение, был как-то такой случай.