Поиск:

Ответ в темуСоздание новой темы Создание опроса
> IUncnown и структура вложенная в него, Не получается извлечь данные из IUnknown 
:(
    Опции темы
franzR
Дата 28.2.2011, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 12.10.2009

Репутация: нет
Всего: нет



Builder6, .Net framework 2.0, WinXP SP3

Доброго времени суток!

Столкнулся с такой проблемой. 
Есть библиотека написанная на .NET, собрана как COM и зарегистрирована на машине. 
Есть проект Builder6, туда подключена эта же либа как COM.

Из COM-библиотеки возвращается некая структура типа Report, которая имеет в себе несколько полей.

Report в SDK имеет вид:
Код

public struct Report 
{
        public string Text;

        public byte[] Data;

        public object Additional_Data;
}


В Builder ипользуется так:
Код

DelphiInterface<ICCNETInterface> initfRef = CreateComObject(CLSID_Iccnet);

Report ans = initfRef->RunCommand(Command_IDENT);

AddLog(ans.Text);

 

В вышеописаном случае текстовый ответ приходит нормально и данные выводятся в лог. Но при попытке доступа к данным которые идут из SDK как object, а в builder они уже IUnknown типа, получается каша если делать так:
Код

DATA_IDENT *obj_id = (DATA_IDENT *)ans.Additional_Data;

AddLog(obj_id->PartNumber);


Данные приходят точно того типа к которому они приведены (DATA_IDENT *), почему не получается доступиться к текстовому полю структуры DATA_IDENT как и в варианте с ans.Text? 

DATA_IDENT структура имеет такой вид:
Код

  public struct DATA_IDENT 
    {
        public string PartNumber;

        public byte[] Number;
    }


Та же проблема и смассивом байт которые приходят в обьекте IUnknown. Не могу понять как их от туда извлечь! smile 

Уважаемые знатоки подскажите выход из ситуации!
PM MAIL   Вверх
simpo
Дата 28.2.2011, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 20.2.2011

Репутация: нет
Всего: нет



С понятием маршалинга знакомы? Если да-покажите как вы это делаете, а если нет - то начните с чтения COM and .NET Interoperability, by Andrew Troelsen
PM MAIL   Вверх
franzR
Дата 28.2.2011, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 12.10.2009

Репутация: нет
Всего: нет



Знаком но очень слабо. Если бы было время разбираться то наверное не задавал бы вопросов, а сел бы и почитал про COM, но увы времени не так много.
Вот для извлечения массива байт из самой Result делаю так:
Код

unsigned char*  __fastcall TForm1::_unpAnswer(SAFEARRAY *sa)
{
    BSTR HUGEP *pbstr;
    SafeArrayAccessData(sa,(void HUGEP**)&pbstr);
    unsigned char *out = (unsigned char*)pbstr;
    return out;
}


использую так:
Код

unsigned char *m = _unpAnswer(ans.Data);


Естественно без проверок на удачное извлечение и прочих предостережений. Пока так.

А вот как вытащить данные из объекта IUnknown пока не могу сообразить. Чет не идет....smile 
PM MAIL   Вверх
simpo
Дата 28.2.2011, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 20.2.2011

Репутация: нет
Всего: нет



Типы СОМ и типы .net напрямую не соответствуют, потому вам необходимо сообщить среде как интерпретировать пришедшую ей из СОМ неуправляемую структуру. Для этого и нужен маршалинг. Делается это с помощью специальных атрибутов,например,marshalas
http://msdn.microsoft.com/en-us/library/sy...sattribute.aspx
нахрапом ваша задача не решиться,придется рабиратся
PM MAIL   Вверх
xvr
Дата 28.2.2011, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 8
Всего: 223



Более того, прямое преобразование типов интерфейса от IUnknown к любому другому в COM запрещена (точнее может работать, а может и не работать). Делайте IUnknown::QueryInterface

PS. По поводу interoperability COM <-> .NET все остается в силе, сначала надо её обеспечить, и только потом заниматься танцами вокруг разных COM интерфейсов  smile 

PM MAIL   Вверх
franzR
Дата 28.2.2011, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 12.10.2009

Репутация: нет
Всего: нет



Посмотрел по ссылке на пример, попробовал сделать следующее:

Код

public struct Report 
{
        [MarshalAs(UnmanagedType.LPStr)]
        public string Text;
        public byte[] Data;
        public object Additional_Data;
}


Но по обращению к полю все равно данные приходят не те что нужно.

Черкните если не сложно, как правильно должно выглядеть объявление структуры понятной потом builder-у. 

Или на практике все таки лучше использовать утилиту Tlbexp.exe которую советует Microsoft? 


PM MAIL   Вверх
simpo
Дата 28.2.2011, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 20.2.2011

Репутация: нет
Всего: нет



tlbexp это,само собой. только код на диезе все равно должен описывать,что именно вы отдаете по СОМ. у вас этого пока нет. + покажите интерфейсы,а то пока разговор ниачем. маршалинг также касается и интерфейсов.
Как описана эта же структура в билдере? как вы ее запрашиваете?

Это сообщение отредактировал(а) simpo - 28.2.2011, 18:07
PM MAIL   Вверх
franzR
Дата 28.2.2011, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 12.10.2009

Репутация: нет
Всего: нет



Вот код-пример либы:

Код

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace MySpace
{
    public interface MyInterface 
    {
          Report GetReport1();

          Report GetReport2();
    }

    [ClassInterface(ClassInterfaceType.None)]
    class MyClass: MyInterface 
    {
        public Report GetReport1()
        {
            Report Result = new Report();

            Result.Text = "MyText";
            Result.Data = new byte[] { 0, 1, 2 };


            //возврат структуры
            AddData1 addData = new AddData1();
            addData.Value1 = "V1";
            addData.Value2 = "V2";
            addData.Value3 = 3;
            Result.Additional_Data = addData;
            return Result;
        }

        public Report GetReport2() 
        {
            Report Result = new Report();

            Result.Text = "MyText";
            Result.Data = new byte[] { 0, 1, 2 };

            //возврат значения энума
            Result.Additional_Data = AddData2.one;
            return Result;
        }


    }

    public enum AddData2 
    { 
        one,
        too
    }


    public struct AddData1
    {
        public string Value1;
        public string Value2;
        public int Value3;
    }



    public struct Report
    {
        public string Text;
        public byte[] Data;
        public object Additional_Data;
    }

}




Описание в Builder получаю автоматически при выполнении Import type library, из предварительно зарегистрированой библиотеки утилитой RegAsm.exe (regasm CCNET.dll /tlb:CCNET.tlb). 
В проект просто добавляется файл .TLB

Так вот структура прописана в сгенерином TLB файле.
Код

struct tagAddData1
{
  LPSTR Value1;
  LPSTR Value2;
  long Value3;
};


Код

enum      AddData2;
struct    tagAddData1;
typedef   tagAddData1 AddData1;


Пытаюсь использовать либу вот так:
Код

DelphiInterface<MyInterface > initfRef = CreateComObject(CLSID_MyInterface);
Report ans = initfRef->GetReport1();
AddLog(ans.Text);

в этом случае в лог выводятся нормальные данные.

Цитата

как вы ее запрашиваете?

Запрашиваю структуру просто вводя ее имя и Builder мне ее подсвечивает. Может я не допонял сам вопрос... 

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

AddData1 *obj_id = (AddData1 *)ans.Additional_Data;
AddLog(obj_id->Value1);

тут пишет кракозяблы.

И вот именно извлечение данных на этом этапе когда идет уже обращение к объекту типа IUnknown которым является ans.Additional_Data и начинаются проблемы.



Это сообщение отредактировал(а) franzR - 28.2.2011, 20:17
PM MAIL   Вверх
xvr
Дата 28.2.2011, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 8
Всего: 223



Я в .NET не специалист, но сдается мне, что в таком виде это работать не будет никогда  smile Вы возвращаете структуру (не унаследованную от IUnknown и не являющуюся интерфейсом) через generic объект. Что там сделает .NET в этом месте один Гейтс знает  smile 
PM MAIL   Вверх
simpo
Дата 28.2.2011, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 20.2.2011

Репутация: нет
Всего: нет



Цитата(franzR @ 28.2.2011,  20:16)

И вот именно извлечение данных на этом этапе когда идет уже обращение к объекту типа IUnknown которым является ans.Additional_Data и начинаются проблемы.

Вы зря пытаетесь передать Additional_Data как object.  Это еще додуматься надо было,если честно. 

Это сообщение отредактировал(а) simpo - 28.2.2011, 23:36
PM MAIL   Вверх
franzR
Дата 2.3.2011, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 12.10.2009

Репутация: нет
Всего: нет



simpo - 28.2.2011, 23:36
Цитата

Вы зря пытаетесь передать Additional_Data как object.  Это еще додуматься надо было,если честно. 


Может и зря но работает отлично, и проблем с использованием в .NET нету. 

Вопрос с IUnknown решился изменением структур на классы и обьяевлением их вот так:

Код

[ClassInterface(ClassInterfaceType.AutoDual)]
public class DATA_IDENT 
    {
        public string PartNumber;
        public byte[] Number;
    }
 
Автоматом сгенерились геттеры и сеттеры для unmanaged.

Со структурами дела обстоят куда сложнее. Пробовал так:
Код

[StructLayout( LayoutKind.Sequential)]
public class DATA_IDENT 
    {
        public string PartNumber;
        public byte[] Number;
    }

Но не отрабатывает, вместо данных каша.

Так же были попытки с двумя другими вариантами StructLayout, но тоже ничего не получилось. 
Как мне показалось из-за того, что в моей структуре поля не строго известной длинны, такие как string и byte[] и указать смещение не получается...
Как бы его можно было бы так выкрутиться? Если это возможно конечно...
PM MAIL   Вверх
simpo
Дата 2.3.2011, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 20.2.2011

Репутация: нет
Всего: нет



Цитата(franzR @ 2.3.2011,  11:03)
Может и зря но работает отлично, и проблем с использованием в .NET нету. 


Давайте определимся,проблем нету или кракозяблы все таки?))) 
PM MAIL   Вверх
franzR
Дата 12.3.2011, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 12.10.2009

Репутация: нет
Всего: нет



simpo:
Цитата

Давайте определимся,проблем нету или кракозяблы все таки?))) 


Давайте определимся))

Цитата

Может и зря но работает отлично, и проблем с использованием в .NET нету. 


Эта фраза адресована к использованию библиотеки в .NET. 

Другое дело использовать ее не получается нормально как COM объект для Builder проекта. В котором собственно и появляются кракозяблы.



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: COM/DCOM/ActiveX/ATL/CORBA | Следующая тема »


 




[ Время генерации скрипта: 0.0635 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.