Опять Assembly->Load... (с++/cli, .net 2.0)
От: uni Россия  
Дата: 25.06.14 23:06
Оценка:
Доброго, уважаемые.

Написал я обёртку для интерфейса Mathcad User EFI. Он предназначен для подключения пользовательских библиотек к Mathcad'у. Интерфейс очень старый и насквозь сишный, прочитать подробно о нём можно в этой доке: Creating a User DLL (pdf).

Так вот, захотелось мне странного — писать эти расширения на .net языках. Сказано — сделано, написал переходник: https://github.com/ViacheslavMezentsev/NetEFI

Стандартно должно работать так. При загрузке Mathcad просматривает специальную директорию (userefi) на предмет наличия dll. Каждую загружает. Если в точке входа применяется функция CreateUserFunction( [структура с описанием функции] ), то Mathcad держит dll в памяти, чтобы потом напрямую вызвать функцию из неё.

Сейчас, если поместить мою сборку (netefi.dll, debug версию) в папку userefi, то она динамически создаст пользовательские функции, которые являются переходниками для функций из .net сборок.

Сторонние сборки должны вести себя как плагины и содержать классы, реализующие интерфейс NetEFI.IFunction, который находится в netefi.dll, т.е. в посреднике. Проблема в том, что у меня не получается загрузить сторонние сборки. Сначала я тестировал функционал на внутренней "функции" — классе test (test.h), который находится прямо внутри netefi.dll. Алгоритм перебора типов при этом работает, но когда я пытаюсь то же самое сделать с внешней сборкой, получаю два вида поведения:

1) Assembly::LoadFrom() — Mathcad в этом месте просто зависает.
2) Assembly::LoadFile() — получаю исключение, что netefi.dll не получается загрузить, хотя он тут же находится.

Тестовая сборка выглядит вот так:

using System;

using NetEFI;


namespace test {

    public class test: IFunction {

        private FunctionInfo _info;

        public FunctionInfo Info {

            get { return _info; }
        }

        public test() {

            _info = new FunctionInfo();

            _info.Name = "test";
            _info.Parameters = "x";
            _info.Description = "test(x)";
            _info.ReturnType = typeof( TComplex );
            _info.Arguments = new[] {typeof ( TComplex ) };
        }

        public FunctionInfo GetFunctionInfo( string lang ) {

            return Info;
        }

        public bool NumericEvaluation( object[] args, ref object result ) {

            TComplex arg0 = (TComplex) args[0];

            result = new TComplex(arg0.Real + 10, arg0.Imaginary + 10);

            return true;
        }

    }

}


Код загрузки находится в netefi.cpp: Manager::LoadAssemblies( HINSTANCE hInstance ). Не мог бы кто ещё раз растолковать как правильно в таком случае загружать сборки? Версию я зафиксировал (звёздочку убрал). Проект можно открыть как в VS2008, так и в VS2012 (но всё равно нужен 2008 для .Net 2.0).

Может быть кто-то ещё подскажет как настроить проект для отладки в смешанном режиме? Сейчас я точки останова могу ставить только для неуправляемого кода. Ещё VS2012 при входе в отладку постоянно спотыкается о какие-то неизвестные исключения, которые я не знаю где сбросить.

В общем, помогите чем сможете.
Re: Опять Assembly->Load... (с++/cli, .net 2.0)
От: uni Россия  
Дата: 26.06.14 10:20
Оценка:
Здравствуйте, uni, Вы писали:

uni>В общем, помогите чем сможете.


Исходники обновил, подписавшись на AssemblyResolve и тупо подставляя свою сборку. Пока работает, но как-то это не красиво:

Assembly^ OnAssemblyResolve(Object^ sender, ResolveEventArgs^ args) {
 
    Manager::LogInfo( String::Format( "OnAssemblyResolve {0}", args->Name ) );
    
    return Assembly::GetExecutingAssembly();
}



void PrepareManagedCode() {

    // Set up our resolver for assembly loading
    AppDomain^ currentDomain = AppDomain::CurrentDomain;

    currentDomain->AssemblyResolve += gcnew ResolveEventHandler( OnAssemblyResolve );
}
Re[2]: Опять Assembly->Load... (с++/cli, .net 2.0)
От: Sinix  
Дата: 26.06.14 11:14
Оценка: +2
Здравствуйте, uni, Вы писали:


uni>Исходники обновил, подписавшись на AssemblyResolve и тупо подставляя свою сборку. Пока работает, но как-то это не красиво:


Такая мысль: что, если проверить лог fusion log viewer?
Похоже, неправильно прописан private bin path или probing path.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.