none
Передача параметра в COM метод на C# RRS feed

  • Общие обсуждения

  • В общем есть подключенный к проекту COM объект, в нужном мне COM классе есть метод. Сигнатура: mScan(ref byte pDevList):void. При попытке передать параметр, выскакивает AccesViolation (попытка чтения или записи в защищенную память). Я так понял, нужно юзать P/Invoke? Как в таком случае передать параметр? 
    14 марта 2013 г. 11:39

Все ответы

  • Так не совсем понятно, откуда куда собираетесь передавать Com -> C# или наоборот?
    14 марта 2013 г. 11:45
    Модератор
  • Из C# в COM, при этом COM метод должен заполнить структуру (передаваемый параметр), который мне потом нужно обработать
    14 марта 2013 г. 12:09
  • Посмотрите данный пример в MSDN.
    14 марта 2013 г. 19:34
    Модератор
  • Да в принципе там то же самое. Только интерфейс у меня уже с классом, поддерживающим этот интерфейс, описаны. Я просто добавляю COM .dll Причем как видно из метода mScan(ref byte pDevList):void сама функция, описанная в .dll принимает ссылку на объект типа List, в который она добавляет айдишники найденных устройств. Как мне в ком передать ссылку на лист, если в сигнатуре стоит ref byte я не пойму.

    Все перерыл, из под .NET видимо такого не сделать...

    Там даже не на объект типа List, в самой .dll параметр описан как [in, out] unsigned char* (посмотрел OleViewer'ом). В C# эквивалент как я понимаю byte (одинаковый размер). Ясное дело, что длл в управляемую память ничего записать не сможет. Но и передать адрес в куче из под .NET я тоже не могу (тупо несовпадение типов). Жесть

    • Изменено tzi0 15 марта 2013 г. 5:45
    15 марта 2013 г. 4:12
  • > Я так понял, нужно юзать P/Invoke?

    Да.

    Сигнатура: mScan(ref byte pDevList):void

    Это где сигнатура так описана?Откуда вы её взяли? Если в некоей документации, то там должно быть описано, что и как передавать.

    > При попытке передать параметр

    Какой параметр передаёте? Как?

    > есть подключенный к проекту COM объект, в нужном мне COM классе

    Давайте с самого начала и поподробнее. Конкретно, что за объект, что за библиотека, дайте ссылку на проект (если это возможно).

    ---

    > при этом COM метод должен заполнить структуру

    Какую структуру? Как она должна быть определена?

    ---

    > сама функция, описанная в .dll принимает ссылку на объект типа List

    Под листом что имеется в виду - System.Collections.Generic.List<T> ?Если да, то почему? И чему равно T ?

    > Как мне в ком передать ссылку на лист, если в сигнатуре стоит ref byte

    Очевидно же - приведение типов.

    > Все перерыл, из под .NET видимо такого не сделать...

    Вот не надо таких громогласных заявлений. .NET как бы и создан, чтобы взаимодействовать с COM.

    > Ясное дело, что длл в управляемую память ничего записать не сможет.

    Ещё как может.

    > Но и передать адрес в куче из под .NET я тоже не могу

    А я могу.

    > тупо несовпадение типов

    Ещё раз: приведение типов.

    15 марта 2013 г. 9:38
  • В общем так.

    Есть некая утилита для работы с платами Atmel, в состав входит API в виде COM объекта, реализованного в .dll. Есть и .tlb файл. Вот с помощью него я сгенерил сборку для .NET и подключил ее к проекту. Если глянуть этот .tlb, то там описан метод таким образом:

    HRESULT AT91Boot_Scan([in, out] unsigned char* pDevList);

    Если смотреть IL DASM'ом, метод выглядит как AT91Boot_Scan: void(uint8&).

    В проекте же, когда я подключаю эту сборку и прописываю неймспейс, в обозревателе объектов метод выглядит как AT91Boot_Scan(ref byte).

    Есть код, написанный на C++, использующий эту библу (рабочий):

    // MANDATORY: Allocate memory for each string in the table
    		for (i=0; i<10; i++)
    			pTest[i] = (unsigned char *)malloc(100);
    
    		// Scan all devices connected
    		pAT91BootDLL->AT91Boot_Scan((unsigned char *)pTest);
    
    		// Print all devices connected
    		i= 0;
    		while (pTest[i] != 0)
    		{
    			printf("Device %d = %s\n\r", i, pTest[i]);
    			i++;
    		}

    Собственно вот, не могу передать ссылку на участок памяти, выделенной как 

    SAMBADLL pAT91BootDLL = new SAMBADLL();
    
                IntPtr pBuff = Marshal.AllocHGlobal(10*100);
    
                pAT91BootDLL.AT91Boot_Scan(pBuff);

    Я и unsafe метод использовал с fixed переменными, результата тоже нет..

    15 марта 2013 г. 10:27
  • Нет никаких предложений? Вот вам и поддержка COM...
    19 марта 2013 г. 10:21
  • Привет

    Как вы экспортируете функцию в C# с помощью P/Invoke? Попробуйте в функцию передавать первый элемент, выделенного в памяти массива, по ссылке так:

    byte[] myarray = new byte[1024];
    pAT91BootDLL.AT91Boot_Scan(ref myarray [0]);

    Или по-другому:

    var ptr = Marshal.AllocHGlobal(size);
    var i = ptr.ToInt32();
    pAT91BootDLL.AT91Boot_Scan(i);


    Для связи [mail]

    19 марта 2013 г. 18:24
  • В первом случае все тот же Аксес виолейшн - попытка чтения или записи в защищенную память.

    Во втором случае ощибка: Argument is 'value' while parameter is declared as 'ref'.

     Пробовал и так еще:

    SAMBADLL pAT91BootDLL = new SAMBADLL();
                    
                unsafe
                {
                    byte** pbyte = stackalloc byte*[5];
                    for (int i = 0; i < 5; i++)
                    {
                        pbyte[i] = (byte*) Marshal.AllocHGlobal(100).ToPointer();
                    }
                    
                    pAT91BootDLL.AT91Boot_Scan(*(byte*)pbyte);
                }
              

    Тоже аксес виолейшн.

    А что значит как я экспортирую функцию? Я просто подключил библиотеку и использую методы определенного в ней класса. Кстати таких методов у меня куча. Не должен же я переписывать вручную все эти методы с параметрами для .NET, tlbimp.exe все за меня уже сделала, или я неправ?

    22 марта 2013 г. 4:11
  • Уважаемый пользователь!

    В вашей теме отсутствует активность в течение последних 5 дней. При отсутствии каких-либо действий в течение 2 последующих дней, тема будет переведена в разряд обсуждений. Вы можете возобновить дискуссию, просто оставив сообщение в данной теме


    Для связи [mail]

    27 марта 2013 г. 12:04