Как создать плагин (дополнение) для SMath Studio

Как создать плагин (дополнение) для SMath Studio - Сообщения

#41 Опубликовано: 19.04.2011 13:53:15
Вячеслав Мезенцев

Вячеслав Мезенцев

1402 сообщений из 1708 понравились пользователям.

Группа: Moderator

Между прочим, плагины можно писать и под линуксом в MonoDevelop'е. Работают, правда что-то с русским текстом кое-где, но пример скомпилировался...
Russia ☭ forever, Viacheslav N. Mezentsev
#42 Опубликовано: 04.08.2011 02:36:08
Andrey Ivashov

Andrey Ivashov

2269 сообщений из 3729 понравились пользователям.

Группа: Super Administrator

Адрес репозитория изменился. Новый путь: https://smath.info/svn/public
1 пользователям понравился этот пост
уни 04.08.2011 16:38:00
#43 Опубликовано: 04.08.2011 16:42:58
уни

уни

156 сообщений из 355 понравились пользователям.

Группа: User

А старые пароли (на запись) уже не работают? Да и анонимный вход что-то не фурычит.
Россия навсегда! Вячеслав Мезенцев
#44 Опубликовано: 05.08.2011 12:00:47
Andrey Ivashov

Andrey Ivashov

2269 сообщений из 3729 понравились пользователям.

Группа: Super Administrator

Старые пароли работают (в том числе и ваш, проверил), а анонимный вход починил - теперь репозиторий снова доступен для просмотра всем желающим.
1 пользователям понравился этот пост
уни 05.08.2011 13:59:00
#45 Опубликовано: 07.08.2011 17:31:12
уни

уни

156 сообщений из 355 понравились пользователям.

Группа: User

Тут имеется хороший веб-интерфейс для исходников: https://github.com/ . Если дублировать заливку кода и туда, то можно иметь относительно простой способ просмотра исходников через броузер. Правда основан он на jit vcs.

Если в форуме когда-нить кто-нить будет обсуждать код, удобно было бы иметь какой-нить непосредственный доступ к хранилищу, минуя клиенты. Как, к примеру, делают на mysvn.ru:
https://mysvn.ru/schoolbell/bell/src/

Здесь, правда, у них очень примитивный доступ. Там есть и trac-система, но она очень мудрёна даже для простого просмотра.

Короче говоря, было бы неплохо иметь возможность на форуме дать ссылку на конкретный листинг конкретного файла и чтобы он открывался в броузере. В github.com есть возможность скачивать исходник в виде архива.
Россия навсегда! Вячеслав Мезенцев
#46 Опубликовано: 07.08.2012 10:12:42
Antech

Antech

2 сообщений из 35 понравились пользователям.

Группа: User

Здравтсвуйте. Я довольно часто пользую базовые функции SMath, но тут появилась необходимость расчета теплофизики воды. У меня есть библиотека моего знакомого (написана на Delphi 32-бит), она бесплатная (Alex.dll по таблицам Александрова). Я решил сделать плагин на C#, чтобы подключить Alex.dll в SMath. Но я совсем не знаю C# (пишу на Visual Fortran и C++). Вчера я весь день занимался тем, чтобы заставить плагин работать. ОК, он запускается. Но возникла проблема с загрузкой неуппавляемой DLL. Как я понял, есть два способа сделать это: DllImport и DllImport+LoadLibrary+GetProcAddress. Ни один способ не заработал!!! Компилируется без ошибок (у меня Visual Studio 2008 Express 32-битная). Но загружать 32-битную DLL не хочет! У меня Win7 x64, компилятор C# (как я понял) 32-битный (в настройках проекта разрядность не нашел), SMath текущая стабильная версия. Симптомы такие:

1. Загрузка через dllImport:
class Import
{
 [DllImport("Alex.dll"]
 public static extern double WtrPrpEntByPrsTempExt(double prs,double temp);
}

...

result=Import.WtrPrpEntByPrsTempExt(argPri,argSec);
Компилится нормально, при вычислении функции в SMath "Была сделана попытка загрузить программу, имеющую неверный формат". Функция выделяется красным, разумеется, нихрена не считается

2. Загрузка через LoadLibrary:
class Import
{
 [DllImport("Kernel32.dll"]
 public static extern IntPtr LoadLibrary(string lpFileName);
}

...

hLib=Import.LoadLibrary("Alex.dll";
Результат - в дебаге (сделал по инструкции SMath для VS Express) видно, что хэндл DLL'а нулевой. Код ошибки (Import.GetLastError) - 193, "не является приложением Win32" (ну это у Микрософта глюкавые сообщения об ошибках, на самом деле то же, что и в первом случае: не является приложением Win64).

Пробовал другие 32-битные DLL (разные) - та же фигня (GetLastError 193). Пробовал 64-битный DLL от Comodo "framework.dll" - прекрасно загружается. Т.е. проблема именно с 32-битным DLL под x64 системой.

Можно ли обойти эту ошибку и загрузить мой любимый 32-битный DLL? Или опять MathCad? Маткад-то прекрасно работает, но хотелось бы SMath...
#47 Опубликовано: 07.08.2012 10:32:27
kmihaylovich

kmihaylovich

8 сообщений из 131 понравились пользователям.

Группа: User

Попробуйте в свойствах вашего проекта (проекта плагина) вместо ANY CPU выставить 32 bit. Вот тут обсуждается этот вопрос: http://stackoverflow.com/questions/3036971/32-bit-dll-importing-in-64-bit-net-application
1 пользователям понравился этот пост
Antech 07.08.2012 11:36:00
#48 Опубликовано: 07.08.2012 11:06:06
Antech

Antech

2 сообщений из 35 понравились пользователям.

Группа: User

kmihaylovich
Спасибо за совет! К сожалению, это не помогло...

В общем, если выставить AnyCPU, то SMath загружает плагин, но функции, разумеется, не работают (32-битный DLL не грузится). Если в плагине выставить x86, то он не загружается: SMath говорит, что не тот формат...

ИМХО SMath сконфигурирован как "Any CPU" и аналогично моему плагину не может загрузить C# DLL плагина, сконфигуренный как x86. Если же делать плагин Any CPU, то он не грузит 32-битный Alex.dll. Что интересно, в Маткаде далеко не такой продвинутый механизм плагинов, но зато он без проблем разботает в x86 и x64. И, что неприятно, мой SMath-файл для параметров топлива будет неполноценный...
#49 Опубликовано: 07.08.2012 14:29:24
tca

tca

11 сообщений из 15 понравились пользователям.

Группа: User

Была такая же проблема для 32 битных dll в 64 битной среде.

Решилась установкой 32 битного флага в файле SMathStudio_Desktop.exe утилитой CorFlags.exe




CorFlags.zip (31 КиБ) скачан 56 раз(а).
1 пользователям понравился этот пост
Antech 07.08.2012 17:26:00
#50 Опубликовано: 07.08.2012 17:26:13
Antech

Antech

2 сообщений из 35 понравились пользователям.

Группа: User

tca
Спасибо! Сейчас уже ночь, как будет возможность - попробую!
#51 Опубликовано: 07.08.2012 21:46:40
уни

уни

156 сообщений из 355 понравились пользователям.

Группа: User

Если работает в Mathcad плагин ваш, то можно попробовать использовать его же через местный плагин UserEFI: http://ru.smath.info/forum/yaf_postst748_Mathcad-EFI-plaghin.aspx
Россия навсегда! Вячеслав Мезенцев
#52 Опубликовано: 08.08.2012 05:32:31
Antech

Antech

2 сообщений из 35 понравились пользователям.

Группа: User

Да, к сожалению, этот C# совершенно неюзабелен по сравнению с нормальным C++.

В общем, скачал CorFlags.exe в составе Framework 4 SDK. Флаг в SMath поменял. Теперь мой плагин приводит к вываливанию SMath (выполняет недопустимую операцию) при нажатии на кнопку выбора функции "f(x)". В режиме дебага происходит то же самое. Ладно, функцию можно ввести, не заходя в окно выбора.
Но теперь возникла другая проблема: хотя указатели на функции, по всей видимости, задаются (это не C++ и как проверить значение указателя на фунцию - неясно), возникает математическая ошибки "потеря точности или переполнение" при обращении к функции Alex.dll (стоит ли говорить, что у меня эта библиотека и на C++, и на Frotran 90 уже годами работает). Попробовал try/catch: Smath на эту ошибку не ругается, но и значение функции не вычисляется, т.е. отвал по catch происходит раньше, чем присваивается результат функции из DLL, что и понятно. В свойствах проекта VS2008 Express никаких опций, относящихся к обработке ошибок, я не нашел. Можно как-то решить эту проблему?

уни
Спасибо за предложение, я бы никогда не смог создать такой хитрый код (хотя у меня есть большие проекты), но я хотел бы через свой плагин подключить. Если не получится, буду пробовать Ваш.

Таки попробовал Ваш интерфейс для Mathcad. Alex.dll прекрасно работает, большое спасибо. Но мне просто интересно: нельзя ли как-то заставить работать мой вариант?
#53 Опубликовано: 08.08.2012 07:09:22
уни

уни

156 сообщений из 355 понравились пользователям.

Группа: User

Мне сложно ответить на этот вопрос, так как я отказался от маршаллинга и по совету в одном посте из рунета написал оболочку на C++/CLI - управляемом C++. Ваш случай я пока не понял, нужно более подробно описать что и как. Вообще же, плагины для SMath Studio можно писать и на управляемом C++. В моём варианте есть особый случай: плагин должен экспортировать функции для того, чтобы подключать Маткад библиотеки и одновременно он должен быть сборкой .Net. Я не знаю можно ли это совместить в одной dll, поэтому разбил проект на две части.

В вашем случае, если подключаемая dll не использует какого-то особого протокола регистрации, думаю можно подключить её через дополнение на C++/CLI. Этот язык специально для этого создавался.
Россия навсегда! Вячеслав Мезенцев
#54 Опубликовано: 08.08.2012 08:45:43
Antech

Antech

2 сообщений из 35 понравились пользователям.

Группа: User

уни
нужно более подробно описать что и как
Я только два дня назад пощупал кроссплатформенный программинг Я использовал C# в Visual Studio 2008 Express. В этом C# делается через маршаллинг (млин, у них там Delegate и Marshall - более технических терминов не нашлось). Т.е. вначале в отдельном классе Import объявляю внешние функции LoadLibrary() и т.д. из DLL (kernel32.dll) через DllImport, а потом - загружаю неуправляемый DLL через LoadLibrary() и получаю указатель на функцию через GetProcAddress (как я и делал всегда на WinAPI). После этого делаю стандартно маршаллинг (правильности типов аргументов проверил) и превращаю указатель в делегат (т.е. в C#-указатель). Но фигня, вероятно, в том, что в этом неуправляемом DLL (Alex.dll) где-то происходит минорная ошибка типа float=double и вылезает ошибка "потеря точности или переполнение" (либо в балуне SMath, если просто запускать, либо в дебагере). А может и более значительная ошибка. При этом в Alex.dll дебагер лезть не хочет, да и исходников от него нет, поэтому отследить где и в чем ошибка я не могу. Да, аргумент(ы) пробовал константами задавать - та же фигня: делегат, установленный на функцию из "водяного" DLL, отваливается с той же ошибкой.

В общем, спасибо за помощь, буду пользовать Ваше гениальное творение. Еще и некий C++/CLI копать - это слишком , времени на него сейчас нету, надо еще и другим заняться...
#55 Опубликовано: 08.08.2012 09:49:16
уни

уни

156 сообщений из 355 понравились пользователям.

Группа: User

"Более подробно" - это означает показать исходный код и желательно весь какой есть, в том числе и тот, где ведётся работа с этой dll на других языках. Дело ещё и в том, что, если это стандартная userefi-dll, то она при старте ищет модуль mcaduser.dll, чтобы зарегистрироваться в системе (Mathcad, SMath), т.е. импортирует некоторые функции оттуда (CreateFunction(), MathcadAllocate(), MathcadFree() и т.д.). Некоторые такие dll после неуспешной регистрации могут просто блокировать работу функций. Т.е. нужна внутренняя логика работы этой dll на всех этапах работы с ней. При работе в составе математической системы они работу с неуправляемой памятью возлагают на эту систему и самостоятельно не выделяют и не освобождают память. Это очень важно, если же эти функции недоступны, то соответственно ничего работать не будет и dll вообще не должна загружаться. Что-то в таком духе.

П.С. Аналогичным способом подключается другая известная библиотека: using Water Steam Pro 6.0.1.36
Россия навсегда! Вячеслав Мезенцев
#56 Опубликовано: 11.08.2012 05:33:23
Antech

Antech

2 сообщений из 35 понравились пользователям.

Группа: User

уни
Извиняюсь, что долго не отвечал. Я использовал Ваш плагин и уже доделал "топливный" файл для SMath.
Исхоный код не показывал, потому что думал, что там все стандартно (хотя часть я показывал выше). Сейчас, наверное, уже нет смысла, потому что если даже оно заработает (что врядли), мне придется в каждой версии SMath поднимать флаг 32BIT. Так что я лучше буду через Ваш плагин подключать.
Что касается регистрации в вызывающей программе, то у меня обычный 32-битный DLL (это мой товарищ написал на Delphi в далеком теперь 2002 году). Все, что нужно для его работы, - LoadLibrary и GetProcAddress.
Про WSP я хнаю, но он платный, а мне нужен freeware. Я в Вашем плагине (в архиве) нашел еще одну реализацию того же IF-97 (XSteam). Она даже работает и free. Попробовал наугад энтальпию в одной точке - на несколько кДж/кг расходится с Alex.dll (хотя в нем, вроде, достаточно точно считается, я когда-то делал сравнение с WSP). В общем, пока что пользую ALex.dll.
#57 Опубликовано: 13.08.2012 12:15:45
уни

уни

156 сообщений из 355 понравились пользователям.

Группа: User

Андрей, не могу понять как рисовать на канве при создании компонента.

Ошибка при отображении изображения

Создал дополнение по аналогии с CheckBoxRegion. Делаю вроде по аналогии:


    class CImageRegionEvaluable : RegionEvaluable {

        internal Image image;

        //...

        public override void OnPaint( PaintEventArgs e ) {

            base.OnPaint( e );

            if ( image != null ) {

                e.Graphics.DrawImage( this.image, 0, 0 );
            }
            
        }
    }


Россия навсегда! Вячеслав Мезенцев
#58 Опубликовано: 13.08.2012 12:21:40
уни

уни

156 сообщений из 355 понравились пользователям.

Группа: User

Изображение гружу так (вставка кода csharp на форуме глючит - нельзя два куска кода в одном сообщении вставить):


        public override void OnEvaluation( Store store ) {        
            // Если параметр области является строкой, то делаем допущение, что это путь к файлу
            if ( ( base.Terms.Length == 1 ) && ( base.Terms[0].Type == TermType.Operand ) && store.IsDefined( Terms[0] ) ) {               
                              
                Term[] out1 = Decision.Preprocessing( Terms, ref store );

                // Вычисляем получившийся вектор
                TDouble out2 = ( TDouble ) SMath.Math.Numeric.Expression.Calculate( out1, store ).obj;

                if ( out2.isText ) {

                    // Убираем обрамляющие кавычки
                    string ImageFileName = out2.Text.Replace( "\"", "" );

                    // Файл должен существовать                    
                    if ( File.Exists( ImageFileName ) ) {

                        base.canv.image = Image.FromFile( ImageFileName );

                    } else {

                        // TODO: Заменить заглушку
                        //throw new FileNotFoundException( "File not found: " + out2.Text );

                    }

                }

            }

        }
В результате, если размеры подвигать, то видно, что размер изображения считывается (я Resize() обрабатываю и не даю изменять размеры), но на компоненте нет загруженного изображения. Не могу понять почему.
Россия навсегда! Вячеслав Мезенцев
#59 Опубликовано: 13.08.2012 18:23:19
Andrey Ivashov

Andrey Ivashov

2269 сообщений из 3729 понравились пользователям.

Группа: Super Administrator

Ответил в скайпе. Суть в том, что вместо
e.Graphics.DrawImage( this.image, 0, 0 );
нужно использовать
e.Graphics.DrawImage( this.image, e.ClipRectangle.X, e.ClipRectangle.Y );
1 пользователям понравился этот пост
уни 14.08.2012 06:17:00
#60 Опубликовано: 13.08.2012 18:51:14
уни

уни

156 сообщений из 355 понравились пользователям.

Группа: User

Да, это сработало, я был невнимателен к оригиналу. Теперь ещё одна проблема: как сделать так, чтобы при первом вычислении размер компонента подстроился под размер загружаемой картинки? Т.е. как правильно изменить размеры? Пробовал после загрузки Resize() вызывать, но не помогло, хотя обработчик этого Resize() у меня чётко "держит" размер картинки при ручном изменении размеров.

Проблема с размером
Россия навсегда! Вячеслав Мезенцев
  • Новые сообщения Новые сообщения
  • Нет новых сообщений Нет новых сообщений