Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Managed обертка для std::Vector

842
03 декабря 2008 года
sigmov
301 / / 16.09.2008
Недавно у меня появилась идея использовать std::vector в С++.
Для этого используя сборку на С++.NET.
В принципе это не особо сложно за одним исключением, я решил сохранить за Вектором возможность хранить произвольные типы (int, double, bool).

Помучившись в течении некоторового времени привожу результат:
Проект С++.Net ClassLibrary VS2008:
Код:
// Vector.h
#pragma once
#include <vector>
#include "stdafx.h"
#include <objbase.h>

using namespace System;
using namespace std;

#define PVOID void*
#define INVI inline virtual
#define IN   inline

namespace VC {
    /* Создание интерфейса с функциями, которые будем использовать*/
    public interface IVECTOR{
        INVI void push_back     ( PVOID var)            =0;
        INVI void pop_back      ()                      =0;
        INVI void erase         (int &index)            =0;
        INVI void inrease       (int &index, PVOID var) =0;
        INVI PVOID back         ()                      =0;
        INVI PVOID front        ()                      =0;
        INVI int size           ()                      =0;
        INVI PVOID operator[]   (int &t)                =0;

    };
    /* Наследуем template Vector от интерфейса, описываем функции интерфейса*/
    template<typename type>
    public class TempVECTOR: public IVECTOR
    {
    public:
        vector<type> Vec;   //Создаем вектор плавающего типа, для последующей работы с ним
        INVI void push_back(PVOID var)              {   Vec.push_back(*(type*)var);                 }
        INVI void pop_back()                        {   Vec.pop_back();                             }
        INVI void erase(int &index)                 {   Vec.erase(Vec.begin()+index);               }
        INVI void inrease(int &index, PVOID var)    {   Vec.insert(Vec.begin()+index,*(type*)var);  }
        INVI PVOID back()                           {   return (PVOID)&Vec.back();                  }
        INVI PVOID front()                          {   return (PVOID)&Vec.front();                 }
        INVI int size()                             {   return Vec.size();                          }
        INVI PVOID operator[](int &t)               {   return (PVOID)&Vec[t];                      }
    };
}
using namespace VC;
//Создаем Вектор и возвращаем его как интерфейс
IVECTOR* Release(TypeCode ctype){
    switch(ctype)
    {
        case TypeCode::Int32:       {return new TempVECTOR<Int32>();break;}
        case TypeCode::Double:      {return new TempVECTOR<Double>();break;}
        case TypeCode::Char:        {return new TempVECTOR<Char>();break;}
        case TypeCode::Boolean:     {return new TempVECTOR<Boolean>();break;}
        case TypeCode::Int64:       {return new TempVECTOR<Int64>();break;}
        case TypeCode::UInt32:      {return new TempVECTOR<UInt32>();break;}
        case TypeCode::SByte:       {return new TempVECTOR<SByte>();break;}
        case TypeCode::Byte:        {return new TempVECTOR<Byte>();break;}
        case TypeCode::Int16:       {return new TempVECTOR<Int16>();break;}
        case TypeCode::UInt16:      {return new TempVECTOR<UInt16>();break;}
        case TypeCode::UInt64:      {return new TempVECTOR<UInt64>();break;}
        case TypeCode::Single:      {return new TempVECTOR<Single>();break;}
    }
    return NULL;
}


////////
namespace VC {
    //Описываем сам переносимый класс
    public ref class Vector
    {
    protected:
        IVECTOR *IV;    //Указатель на интерефейс вектора типа(TypeCode ctype)
    public:
        //Конструктор вектора базового типа
        Vector(TypeCode ctype)              {IV=Release(ctype);}
        inline void push_back(PVOID var)    {IV->push_back(var);}
        inline void pop_back()              {IV->pop_back();}      
        inline void erase(int index)        {IV->erase(index);}
        inline void increase(int index,PVOID var)                                              
                                            {IV->inrease(index,var);}      
        inline PVOID back()                 {return IV->back();}
        inline PVOID front()                {return IV->front();}
        inline int size()                   {return IV->size();}
        inline PVOID top(int t)             {return (*IV)[t];}
    };
}


Основные недостатки:
1) Среди хранимых типов данных доступны только типы System::TypeCode. И то лишь те, которые имеют фиксированный размер.
2) Возвращаемые значения имеют тип void* (PVOID - в коде), что приводит к необходимости, допустим возвращая тип (int) в С# писать следующие конструкции: *(int*)vec.back().

И вот следующие вопросы:
1) Как в С# получать указатели на небазовые простые классы, а допустим получить указатель или адресс переменной типа System::String, не говоря уже допустим про структуры.
2) Есть ли возможность наладить восприятие generic<typename gtype> ~ template<typename ttype>, т.е. перевести generic тип в native code.

Буду рад любым вашим идеям.:)
562
03 декабря 2008 года
tarekon
175 / / 19.08.2003
Зачем тебе всё это???

Цитата:
1) Как в С# получать указатели на небазовые простые классы, а допустим получить указатель или адресс переменной типа System::String, не говоря уже допустим про структуры.


Что такое "небазовый простой класс"? Переформулируй, плиз

Цитата:
2) Есть ли возможность наладить восприятие generic<typename gtype> ~ template<typename ttype>, т.е. перевести generic тип в native code.


Читай про Object class и его метод GetType. В обертке делай преобразование. Вообще эта задача в общем виде нерешаемая, т.к. generic<typename gtype> - это конструкция времени исполнения, а template<typename ttype> - конструкция времени компиляции. Сформулировал криво, но, надеюсь, смысл понятен.

842
03 декабря 2008 года
sigmov
301 / / 16.09.2008
Цитата: tarekon
Что такое "небазовый простой класс"? Переформулируй, плиз



Вернее будет сказать небазовый простой тип. Unsafe code C# поддерживает указатели на базовые value типы (там int, byte, float, double, .....).
Поэтому при аолучении (void*) указателя его сожно преобразовать допустим в inf следующей процедурой: *(int*)(указатель типа void*).
А если допустим у меня кть потребность закинуть туда:
struct XY{ int x,y; };
Тогда ее уже не вытащишь *(XY*)(указатель типа void*) потому как компилятор скажет что указатели на XY невозможен.

Я вроде как нашел, что для этой цели можно использовать System::IntPtr, вот только как это корректно сделать - я не нашел.

Мож кто знает?

341
03 декабря 2008 года
Der Meister
874 / / 21.12.2007
 
Код:
generic <typename T>
public ref class Vector
    where T : ISerializable
{
};

Хотя, если чесно, фигнёй страдаете. В FCL есть более гибкие и удобные коллекции (например, вариации на тему List).
И ещё не ясно, зачем передавать ссылки на int в erase() и increase().
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог