Русскоязычный форум закрыт из-за отсутствия активности (доступен только для чтения).
Пожалуйста, пользуйтесь англоязычной его версией. Приносим извинения за неудобства
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline mikekaganski  
#1 Оставлено : 12 февраля 2015 г. 10:57:54(UTC)
mikekaganski


Статус: Advanced Member

Группы: Registered
Зарегистрирован: 19.03.2012(UTC)
Сообщений: 112
Мужчина
Российская Федерация
Откуда: Khabarovsk, Russia

Сказал «Спасибо»: 130 раз
Поблагодарили: 33 раз в 29 постах
Здравствуйте!

Описал проблему в английской ветке. По предложению Вячеслава дублирую тему здесь.

При возврате из плагина результата в виде TNumber и присвоении ему единиц измерения через его obj.Units результат прекрасно виден, но ведёт себя как будто эти единицы неизвестны программе. Как сделать назначение единиц правильно?

При возврате из функции строкового значения через

new SMath.Math.Numeric.TDouble("\"" + String + "\"" );

текст возвращается нормально, но использовать такую функцию внутри функций SMath, которым нужна строка, нельзя - возникает ошибка "Требуется строка!"
Как это делать правильно?

В архиве проект плагина C#, созданный в VS2013. Там же тестовый файл debug.sm с демонстрацией проблемы. При компиляции отладочной версии DLL плагина копируются в папку "%appdata%\SMath\extensions\plugins\ca92ef03-c7da-4888-98ad-528482733e2f\1.0.0.0\" (должна существовать).

Заранее спасибо за подсказки и указание направления!
С уважением,
Михаил Каганский
Offline уни  
#2 Оставлено : 12 февраля 2015 г. 23:29:08(UTC)
уни


Статус: Advanced Member

Группы: Registered
Зарегистрирован: 02.06.2009(UTC)
Сообщений: 346
Мужчина
Российская Федерация

Сказал «Спасибо»: 50 раз
Поблагодарили: 151 раз в 103 постах
Я посмотрел исходники, которые выложил в репозиторий Давид. Если этот вариант рабочий (не пробовал), то от себя могу порекомендовать использовать вместо NumericEvaluation обработчик ExpressionEvaluation. Странно, что понадобилась какая-то дополнительная работа с размерностями. Насколько я понимаю, нужно обезразмерить параметры функции на входе и добавить размерность на выходе. Почему так это сложно получилось? Весь код для работы с размерностями должен быть на стороне SMath Studio.

Может потребовать пояснение использование метода UnitsManager.GetCurrentUnitName(). В SMath Studio принято соглашение, что "твёрдая" копия файла расчёта не должна зависеть от локализации. Поэтому существуют стандартные (для программы) идентификаторы для названий математических функций, а также соглашения для разделителей и некоторых других символов. По-видимому, то же касается единиц измерения. Поэтому после численного расчёта к результату в виде строки достаточно добавить (буквально) нужную по документации размерность. Проще всего (и понятней) это делать "вручную" в обработчике ExpressionEvaluation, где доступен экземпляр Store.

Проект копировался или создавался мастером? GUID должен быть уникальным. Если копировать шаблон из другого проекта, то нужно заново генерировать GUID, который находится в файле AssemblyInfo.cs. Мастер делает это автоматически.

П.С. А вообще, лучше использовать обёртку, которая написана самими авторами (platform-independent.7z). Там есть и пример как ей пользоваться (Example.cs). Наворотили они там предостаточно. Не понимаю зачем нужен такой сложный код, но авторам видней. Достаточно взять их обёртку и совместить с кодом плагина для SMath Studio. Я и автору это же посоветовал, так как видел у них на сайте описание обёртки на c#. Не знаю почему он так долго код ваяет, видимо он решил делать нативную обёртку на C++/CLI по моим примерам, а она в два (и более) раза сложнее, чем то же на c#.

Отредактировано пользователем 13 февраля 2015 г. 0:16:21(UTC)  | Причина: Не указана

Вложение(я):
platform-independent.zip (13kb) загружен 36 раз(а).
Россия навсегда!
Вячеслав Мезенцев
thanks 1 пользователь поблагодарил уни за этот пост.
mikekaganski оставлено 13.02.2015(UTC)
Offline mikekaganski  
#3 Оставлено : 13 февраля 2015 г. 3:47:02(UTC)
mikekaganski


Статус: Advanced Member

Группы: Registered
Зарегистрирован: 19.03.2012(UTC)
Сообщений: 112
Мужчина
Российская Федерация
Откуда: Khabarovsk, Russia

Сказал «Спасибо»: 130 раз
Поблагодарили: 33 раз в 29 постах
Вячеслав, огромное спасибо за анализ!

Автор: уни Перейти к цитате
от себя могу порекомендовать использовать вместо NumericEvaluation обработчик ExpressionEvaluation.

По правде говоря, сначала я и сам пошёл этим путём. Я хотел сначала реализовать только IPluginLowLevelEvaluation, без IPluginMathNumericEvaluation. Тем более что, по моим наблюдениям, НЕ реализовывать IPluginLowLevelEvaluation совсем нельзя, нужна хотя бы заглушка: SMath ругается, когда пытаешься добавить единицы измерения в выражении, где есть функция плагина "чистого IPluginMathNumericEvaluation". Но меня напрягало, во-первых, усложнение подготовки численного значения параметров (параметры передаются не как готовое число/строка, а как массив Term), и во-вторых, то, что это может как-то сказаться на работе SMath: ведь я заставляю SMath безальтернативно производить численное решение подвыражений в аргументах, независимо от режима оптимизации выражения, выбранного пользователем. Ведь, судя по информации о последовательности вычислений, представленной Андреем в теме о разработке плагинов, ExpressionEvaluation выполняется перед другими, и независимо от метода оптимизации? Я впервые делаю плагин для SMath, да и вообще моё знакомство с .NET исключительно маргинальное, так что я подумал: пусть математикой занимается сама программа, ведь у меня фактически используется просто численная библиотека, а IPluginMathNumericEvaluation по логике как раз предназначен для этого?
Автор: уни Перейти к цитате
Странно, что понадобилась какая-то дополнительная работа с размерностями. Насколько я понимаю, нужно обезразмерить параметры функции на входе и добавить размерность на выходе. Почему так это сложно получилось? Весь код для работы с размерностями должен быть на стороне SMath Studio.

Может потребовать пояснение использование метода UnitsManager.GetCurrentUnitName(). В SMath Studio принято соглашение, что "твёрдая" копия файла расчёта не должна зависеть от локализации. Поэтому существуют стандартные (для программы) идентификаторы для названий математических функций, а также соглашения для разделителей и некоторых других символов. По-видимому, то же касается единиц измерения. Поэтому после численного расчёта к результату в виде строки достаточно добавить (буквально) нужную по документации размерность.

Меня тоже это удивило. По-видимому, в NumericEvaluation это именно так.
Вначале в этом обработчике я пытался просто использовать выражения типа new MItem("'J/'mol" ). Но это оказалось неправильным, потому что результат оказывался для программы "непонятным", в локализованной версии отображались английские названия единиц, и вели они себя просто как невстроенные и непривязанные единицы. При использовании для единиц GetCurrentUnitName() отображение их выправилось, но поведение осталось: программа не воспринимала их как встроенные единицы, если только они не оказывались "базовыми" единицами SI (такими как Кельвины или метры, в отличие от, скажем, Джоулей), да и те не работали, если выражение было сложным (скажем, м^3 или кг/м). И только после последовательного разбиения составных единиц SI на простые, использования UnitsManager.GetCurrentUnitName() для каждой единицы по отдельности, формирования строки-выражения составной единицы, Converter.ToMItem() и Expression.SimplifyEx() получилось то, чего хотелось достичь. При этом в "твёрдой" копии сохраняются именно стандартные единицы, не зависящие от локализации.

Для того, чтобы понять, что так вроде бы "правильно", я посмотрел, как SMath передаёт образмеренные параметры в функцию. Там для любой сложной единицы получается внутреннее разложенное представление в локализованных именах. Я так и сделал.

Я считаю, что просто в UnitsManager не хватает метода, создающего сразу нормальный MItem из языконезависимого базового представления, ведь у него есть весь необходимый контекст из файла. Было бы здорово написать что-то типа UnitsManager.MakeLocaleIndependentUnit("'J/'mol" ), ну, или (если так уж необходимо ограничится только встроенными единицами, учитывая разложение [J] = [kg*m^2/s^2]) UnitsManager.MakeLocaleIndependentUnit("'kg*'m^2/{'s^2*'mol}" ). Это обеспечило бы возможность нормально работать с единицами в NumericEvaluation() без плясок с бубном. Но это - вопрос расширения функционала к Андрею.
Автор: уни Перейти к цитате
Проще всего (и понятней) это делать "вручную" в обработчике ExpressionEvaluation, где доступен экземпляр Store.

Может быть, но с другой стороны, там труднее с числами (я писал выше, что у меня нет полного представления о возможных побочных явлениях этого подхода, а пляски с единицами в NumericEvaluation, при всей их экзотичности, выглядят "стабильными" без побочных эффектов). Может быть, я ошибаюсь.
Автор: уни Перейти к цитате
Проект копировался или создавался мастером? GUID должен быть уникальным. Если копировать шаблон из другого проекта, то нужно заново генерировать GUID, который находится в файле AssemblyInfo.cs. Мастер делает это автоматически.

Мастером. Я использовал в качестве отправной точки Ваш VBNetPlugin, но только как источник кода, а не проекта. Кстати, огромное спасибо! Без этого было бы гораздо труднее получить первое работающее приближение.
Автор: уни Перейти к цитате
А вообще, лучше использовать обёртку, которая написана самими авторами (platform-independent.7z). Там есть и пример как ей пользоваться (Example.cs). Наворотили они там предостаточно. Не понимаю зачем нужен такой сложный код, но авторам видней. Достаточно взять их обёртку и совместить с кодом плагина для SMath Studio. Я и автору это же посоветовал, так как видел у них на сайте описание обёртки на c#. Не знаю почему он так долго код ваяет, видимо он решил делать нативную обёртку на C++/CLI по моим примерам, а она в два (и более) раза сложнее, чем то же на c#.

Я думаю, что им нужно делать на C#, несмотря на то, что лично мне этот язык не нравится. Но для данной платформы это - то, что нужно.
Использовать их обёртку не хочу - я в ней не разобрался, пусть сами используют, я просто сделал для них старт. Она какая-то слишком избыточная. Мне кажется, тут всё проще, логика каждой функции чётко прописана в своём классе.
С уважением,
Михаил Каганский
Offline уни  
#4 Оставлено : 13 февраля 2015 г. 9:05:47(UTC)
уни


Статус: Advanced Member

Группы: Registered
Зарегистрирован: 02.06.2009(UTC)
Сообщений: 346
Мужчина
Российская Федерация

Сказал «Спасибо»: 50 раз
Поблагодарили: 151 раз в 103 постах
Похоже, что авторам было лень самим разбираться в том как работает маршаллинг и прочие премудрости использования нативного кода в c#. Они использовали универсальную обёртку с сайта http://www.swig.org , которая обёртывает код автоматически. Поэтому он получается такой избыточный. Я могу попробовать сделать пример с использованием их обёртки.

Что касается IPluginLowLevelEvaluation. При всех его недочётах я практически во всех своих дополнениях использовал именно этот обработчик, даже в чисто численных (MathcadFileAccess). Можно взять любой мой плагин и посмотреть как работать в IPluginLowLevelEvaluation. В MathcadFileAccess я тоже сначала решил, что с IPluginMathNumericEvaluation будет проще, но потом весь код переделал под IPluginLowLevelEvaluation. Этот обработчик даёт большую степень свободы для программиста.

Твой код (давай на ты) как-то неправильно работает со строками. Функция, которая возвращает версию вываливается с ошибкой. Честно говоря, я так и не понял пока почему.

Меня смутило также использование StringBuilder в качестве типа параметра для работы с нативными функциями из библиотеки CoolProp.dll. Обычно для этого используются более примитивные классы. Я потому и рекомендовал использовать их вариант обёртки, т.к. у них эта переходная часть должна была быть записана правильно.

Цитата:
Использовать их обёртку не хочу - я в ней не разобрался, пусть сами используют, я просто сделал для них старт.

Они о "старте" мыслят немного по-другому. Вот ссылка на консольный проект, который я собрал для пробы их обёртки: CoolPropConsole-x32.zip. В проекте есть файл CoolProp.dll - это специальная 32-разрядная сборка библиотеки для использования с обёрткой (насколько я понял). Этот файл можно скачать с sf.net, там есть папка CoolProp\Csharp\Windows32. Исходники из platform-independent.7z нужно положить в отдельную папку проекта. Далее я просто скопировал содержимое Example.cs в свой проект. Всё достаточно просто.

Отредактировано пользователем 13 февраля 2015 г. 9:24:48(UTC)  | Причина: Не указана

Россия навсегда!
Вячеслав Мезенцев
Offline mikekaganski  
#5 Оставлено : 13 февраля 2015 г. 10:08:16(UTC)
mikekaganski


Статус: Advanced Member

Группы: Registered
Зарегистрирован: 19.03.2012(UTC)
Сообщений: 112
Мужчина
Российская Федерация
Откуда: Khabarovsk, Russia

Сказал «Спасибо»: 130 раз
Поблагодарили: 33 раз в 29 постах
Автор: уни Перейти к цитате
Что касается IPluginLowLevelEvaluation. При всех его недочётах я практически во всех своих дополнениях использовал именно этот обработчик, даже в чисто численных (MathcadFileAccess). Можно взять любой мой плагин и посмотреть как работать в IPluginLowLevelEvaluation. В MathcadFileAccess я тоже сначала решил, что с IPluginMathNumericEvaluation будет проще, но потом весь код переделал под IPluginLowLevelEvaluation. Этот обработчик даёт большую степень свободы для программиста.

Спасибо, я посмотрю.
Автор: уни Перейти к цитате

Твой код (давай на ты) как-то неправильно работает со строками. Функция, которая возвращает версию вываливается с ошибкой. Честно говоря, я так и не понял пока почему.

Я тоже не понял. Я её и выделил в тестовом файлике. Может быть, это как раз из-за численной природы вычисления...
Автор: уни Перейти к цитате
Меня смутило также использование StringBuilder в качестве типа параметра для работы с нативными функциями из библиотеки CoolProp.dll.

Я не силён в .NET. Посмотрел здесь: https://msdn.microsoft.c...us/library/e8w969hb.aspx
Там третья строка - "By reference. Passes strings as In/Out parameters using StringBuilder."
И оттуда - пример: https://msdn.microsoft.c...us/library/x3txb6xc.aspx
В GetSystemDirectory передаются буфер и его размер - как раз мой случай. Я не стал с низкоуровневыми структурами мудрить, раз этот класс специально для этого реализован. Если бы пришлось туда передавать структуру - тогда да, тогда IntPtr, Marshal.AllocHGlobal() etc... Или у варианта со StringBuilder есть проблемы?
С уважением,
Михаил Каганский
Offline mikekaganski  
#6 Оставлено : 14 февраля 2015 г. 0:16:15(UTC)
mikekaganski


Статус: Advanced Member

Группы: Registered
Зарегистрирован: 19.03.2012(UTC)
Сообщений: 112
Мужчина
Российская Федерация
Откуда: Khabarovsk, Russia

Сказал «Спасибо»: 130 раз
Поблагодарили: 33 раз в 29 постах
Вячеслав, скажи, а можно ли код

var arg1 = SMath.Math.Decision.Preprocessing(arg, ref context);
return SMath.Math.Numeric.Expression.Calculate(arg1, context).obj as SMath.Math.Numeric.TDouble;


сократить до

return SMath.Math.Decision.NumericCalculation(arg, ref context).obj as SMath.Math.Numeric.TDouble;

В смысле, это одно и то же, или есть побочные эффекты/разница в результате? Я вроде не вижу разницы в результатах, но кто его знает, может, при определённых исходных...
С уважением,
Михаил Каганский
Offline уни  
#7 Оставлено : 14 февраля 2015 г. 9:09:31(UTC)
уни


Статус: Advanced Member

Группы: Registered
Зарегистрирован: 02.06.2009(UTC)
Сообщений: 346
Мужчина
Российская Федерация

Сказал «Спасибо»: 50 раз
Поблагодарили: 151 раз в 103 постах
Честно говоря, не знаю тонкостей NumericCalculation(). Подсказать не могу. Тут нужно у Андрея спросить. Вообще, рекомендую скачать с рутрекера Resharper 9.0, это специальный плагин для студии, который позволяет упрощать конструкции (он делает подсказки в коде, кроме прочего). Он может убрать рудиментарный код, т.е. тот, который писать не обязательно. Всё делается автоматически.

По поводу использования того или иного метода. Я иногда, если не знаю что делает метод и как им пользоваться, делаю поиск по всем исходникам плагинов (они у меня закачаны из репозитория). Посмотрев на примеры можно сделать определённые выводы.

Отредактировано пользователем 14 февраля 2015 г. 9:11:52(UTC)  | Причина: Не указана

Россия навсегда!
Вячеслав Мезенцев
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.