Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: как связать Unmanaged и managed (c++ / c#)  (Прочитано 5029 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« : 11-05-2009 14:08 » 

Проблема:
есть код функции на с++, для него надо исправить вреппер на с#...

Сторона на с++ выглядит так:

Код:
bool myclass::CreateChildObjects(clsObject* parent, clsClass *child_class, UINT32 number, clsObject**& created_objects).

Все объекты, кроме последнего, являются входящими, последний - выходящий, т.е. функция создает серию объектов и помещает их в наш контейнер created_objects.

Коллега реализовал вреппер так:
Код:
bool  UManaged::myclass::CreateChildObjects(UManaged::clsObject^parent, UManaged::clsClass^ child_class, UINT32 number, UManaged::clsObject^ created_objects)
{
  bool  error;

  clsObject *om_parent = parent->UnmanagedObject;
  OMS::Class  *om_child_class = child_class->UnmanagedObject;
  clsObject** om_created_objects = new clsObject*[number];

  error = this->popul->CreateChildObjects(oms_parent, oms_child_class, number, oms_created_objects);

  return error;
}

При этом передать дальше по цепочке результат работы функции товарищ забыл...
А я тоже не соображу как, ибо не знаю - никогда этого не делала...

Единственное, что мне в любом случае ясно -
Код:
UManaged::clsObject^ created_objects

уже само по себе ошибочно, т.к. мне нужен массив объектов, а не один единственный объект.

Подскажите, пожалуйста, куда копаем?
Записан

холоднокровней, Маня, Ви не на работе
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 11-05-2009 14:39 » 

Цитата: Malaja
Коллега реализовал вреппер
Однако, это C++.NET, а не C#.NET.

Сейчас подумаю и примерчик соберу, если выйдет.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #2 : 11-05-2009 14:50 » 

dimka,

пардон, неверно написала, посему исправляюсь:
Код, для которого нужен вреппер - на с-шарпе, а сам вреппер - на с++

Спасибочки заранее!
Записан

холоднокровней, Маня, Ви не на работе
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 11-05-2009 15:10 » 

У меня возникли некоторые вопросы.

1) Пространство имён UManaged используется для классов на чистом C++, вне этого пространства классы на .NET?
2) Если на пункт 1 ответ положительный, то не понятно, что за свойство UnmanagedObject есть у объекта на чистом C++? Если бы у класса-.NET-обёртки было такое свойство - это я бы ещё понял...
3) Правильно ли я понимаю, что выходной массив created_objects внутри неуправляемого кода лишь заполняется, т.е. неуправляемый код не выделяет память?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #4 : 11-05-2009 15:59 » 

dimka,
1) UManaged - это пространство из managed - классов, а не чистый с++.
3) да, так было сделано - тот, кто вызывает функцию, должен создать память, дабы потом иметь возможность ее и очистить, а функция только заполняет выделенную память
Записан

холоднокровней, Маня, Ви не на работе
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 11-05-2009 16:32 » 

Поразбирался и запутался в архитектуре твоего решения - нужна дополнительная информация.

1) В неуправляемом коде есть классы и массивы их объектов. Вида
Код: (Text) C++.NET
class C {};

void createPointersArray(int size, C **&pointersArray)
{
        pointersArray = new C *[size];
}

int main(array<System::String ^> ^args)
{
        C **pointersArray = NULL;
        createPointersArray(10, pointersArray);
        delete[] pointersArray;
        return 0;
}

2) В управляемом коде есть классы и массивы их объектов. Вида
Код: (Text) C++.NET
ref class C {};

void createArray(int size, array<C ^> ^%arrayInstance)
{
        arrayInstance = gcnew array<C ^>(size);
}

int main(array<System::String ^> ^args)
{
        array<C ^> ^arrayInstance = nullptr;
        createArray(10, arrayInstance);
        // delete не нужен, его осуществляет сборщик мусора.
        return 0;
}


Как у вас работают обёртки?

Каждый объект класса из неуправляемого кода имеет объект-обёртку в управляемом коде, а массивы в неуправляемом коде?

Каждый объект класса из неуправляемого кода имеет объект-обёртку в управляемом коде, а массивы из неуправляемого кода каким-либо образом отображаются в массивы в управляемом коде?

Следует учитывать, что в неуправляемом коде массив - это кусок памяти, а в управляемом коде массив - это объект класса System::Array, так что приведение типов "в лоб" невозможно.

Какова роль обёрток в проекте? Какие части управляемого кода осуществляют управление памятью в неуправляемом коде?
« Последнее редактирование: 11-05-2009 16:41 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #6 : 11-05-2009 17:12 » 

Дим,

что-то в этом роде Ага
Сначала все было написано на с++, потом появилась необходимость использования кода на с-шарпе, что привело к появлению оберток вокруг всех объектов и функций.
Т.о. таки каждый класс (и все его объекты соответственно) имеют обертки (ну или должны их иметь. Хотя периодически выясняется, что чего-то не хватает).

насчет массивов: можно ли в таком случае сделать нечто в таком духе:
1)создаем в с-шарпе массив
Код:
UManaged::clsObject[] arr = new UManaged::clsObject[5];
2) в вызове обертки должно стоять :
Код:
bool  UManaged::myclass::CreateChildObjects(UManaged::clsObject^parent, UManaged::clsClass^ child_class, UINT32 number, ref UManaged::clsObject[] created_objects)
3) после получения заполненного массива сделать поэлементное присвоение:
Код:
UManaged::clsObject[i] = om_created_objects[i] ;
Ибо в этом случае нас не интересует, где и как выделена память.
Или мысль в корне неверна?
Записан

холоднокровней, Маня, Ви не на работе
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 11-05-2009 19:44 » 

Malaja, мысль верная, только не до конца додуманная. Остаётся вопрос об управлении памятью в неуправляемом коде.

Положим, исходно есть массив объектов в неуправляемом коде.

Требуется преобразовать его в массив в управляемом коде объектов в управляемом коде.

Положим:
- исходный массив копируем в целевой, после чего исходный уничтожаем;
- каждый объект в исходном массиве помещаем в обёртку в управляемом коде, которая обеспечивает управление памятью.

Код: (Text) C++.NET
#include <cstdlib>

using namespace System;

namespace UManaged
{
        class C
        {
        private:
                int id;
        public:
                C(const int id):
                        id(id)
                {
                        Console::WriteLine(
                                "Create unmanaged instance id={0}",
                                this->id);
                }

                ~C()
                {
                        Console::WriteLine(
                                "Free unmanaged instance id={0}",
                                this->id);
                }

                int getID() const
                {
                        return this->id;
                }
        };
}

namespace Managed
{
        ref class C
        {
        private:
                UManaged::C *unmanagedInstance;
        public:
                property UManaged::C *UnmanagedInstance
                {
                        UManaged::C *get()
                        {
                                return this->unmanagedInstance;
                        }
                }

                C(UManaged::C *unmanagedInstance):
                        unmanagedInstance(unmanagedInstance)
                {
                        Console::WriteLine(
                                "Create managed wrapper for unmanaged instance id={0}",
                                this->unmanagedInstance->getID());
                }

                ~C()
                {
                        this->!C();
                }

                !C()
                {
                        Console::WriteLine(
                                "Free managed wrapper for unmanaged instance id={0}",
                                this->unmanagedInstance->getID());
                        delete this->unmanagedInstance;
                }
        };
}

void createSourceArray(UManaged::C **&a, int &size)
{
        Console::WriteLine("Create unmanaged array of pointers to unmanaged instances.");
        size = 10;
        a = new UManaged::C *[size];
        for(int i = 0; i < size; ++i)
        {
                a[i] = new UManaged::C(i);
        }
}

void convertSourceToDestination(UManaged::C **&source, int size, array<Managed::C ^> ^%destination)
{
        Console::WriteLine("Create managed array of pointers to unmanaged instances.");
        destination = gcnew array<Managed::C ^>(size);
        for(int i = 0; i < size; ++i)
        {
                UManaged::C *sourceInstance = source[i];
                Managed::C ^destinationInstance = gcnew Managed::C(sourceInstance);
                destination[i] = destinationInstance;
        }
        Console::WriteLine("Delete unmanaged array of pointers, but keep unmanaged instances.");
        delete[] source;
        source = NULL;
}

void test()
{
        UManaged::C **source = NULL;
        array<Managed::C ^> ^destination = nullptr;
        int size = 0;

        createSourceArray(source, size);
        convertSourceToDestination(source, size, destination);

        Console::WriteLine("Work with managed array.");
        for each(Managed::C ^instance in destination)
        {
                Console::WriteLine("Work with instance id={0}", instance->UnmanagedInstance->getID());
        }
}

int main(array<System::String ^> ^args)
{
        test();

        GC::Collect(GC::MaxGeneration, GCCollectionMode::Forced);
        Console::ReadLine();
        return 0;
}

Отладочный вывод
Код:
Create unmanaged array of pointers to unmanaged instances.
Create unmanaged instance id=0
Create unmanaged instance id=1
Create unmanaged instance id=2
Create unmanaged instance id=3
Create unmanaged instance id=4
Create unmanaged instance id=5
Create unmanaged instance id=6
Create unmanaged instance id=7
Create unmanaged instance id=8
Create unmanaged instance id=9
Create managed array of pointers to unmanaged instances.
Create managed wrapper for unmanaged instance id=0
Create managed wrapper for unmanaged instance id=1
Create managed wrapper for unmanaged instance id=2
Create managed wrapper for unmanaged instance id=3
Create managed wrapper for unmanaged instance id=4
Create managed wrapper for unmanaged instance id=5
Create managed wrapper for unmanaged instance id=6
Create managed wrapper for unmanaged instance id=7
Create managed wrapper for unmanaged instance id=8
Create managed wrapper for unmanaged instance id=9
Delete unmanaged array of pointers, but keep unmanaged instances.
Work with managed array.
Work with instance id=0
Work with instance id=1
Work with instance id=2
Work with instance id=3
Work with instance id=4
Work with instance id=5
Work with instance id=6
Work with instance id=7
Work with instance id=8
Work with instance id=9
Free managed wrapper for unmanaged instance id=9
Free unmanaged instance id=9
Free managed wrapper for unmanaged instance id=0
Free unmanaged instance id=0
Free managed wrapper for unmanaged instance id=8
Free unmanaged instance id=8
Free managed wrapper for unmanaged instance id=7
Free unmanaged instance id=7
Free managed wrapper for unmanaged instance id=6
Free unmanaged instance id=6
Free managed wrapper for unmanaged instance id=5
Free unmanaged instance id=5
Free managed wrapper for unmanaged instance id=4
Free unmanaged instance id=4
Free managed wrapper for unmanaged instance id=3
Free unmanaged instance id=3
Free managed wrapper for unmanaged instance id=2
Free unmanaged instance id=2
Free managed wrapper for unmanaged instance id=1
Free unmanaged instance id=1
« Последнее редактирование: 11-05-2009 19:52 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #8 : 12-05-2009 08:17 » 

Дим,
огромное тебе спасибо!!! Разобралась!
Еще раз прошу прощения за беспокойство!

Вывод- надо срочно учить матчасть ;-(
Записан

холоднокровней, Маня, Ви не на работе
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines