Для сопряжения С++ библиотеки и VB программы решил для представления объектов С++ использовать хендлы и процедурно-ориенторованный API (подобно WinAPI). Хендлы предполагаю хранить в ассоциативном массиве, в парах целое число — объект.
Проблема в том, что объекты могут быть разных типов (классов). Варианты решения:
1) Поддерживать несколько таблиц хендлов — каждого типа отдельно, но тогда кол-во функций в API комбинаторно возрастает.
2) Различать тип объекта по хендлу. Например, разбить весь диапазон возможных значений хендлов на зарезервированные интервалы, и по интервалу определять тип, после чего делать соответствующий reinterpret_cast. Немного коряво и хаковато, зато типы могут быть совершенно независимы. (reinterpret_cast конечно хак, но система хендлов вообще — хак с точки зрения С++, а альтернативы ей я не вижу).
3) Наследовать все классы от одного интерфейса. Однако, если классы слишком разные, в этом обшем предке может вообще не оказаться полиморфных методов. Придется как-то даункастить, а этого хотелось бы избежать.
Здравствуйте, Ignoramus, Вы писали:
I>Для сопряжения С++ библиотеки и VB программы решил для представления объектов С++ использовать хендлы и процедурно-ориенторованный API (подобно WinAPI). Хендлы предполагаю хранить в ассоциативном массиве, в парах целое число — объект.
I>Проблема в том, что объекты могут быть разных типов (классов). Варианты решения:
Здравствуйте, Владислав Сомов, Вы писали:
ВС>Здравствуйте, Владислав Сомов, Вы писали:
ВС>>б) Хранить целое — объект-обертку, содержащую ссылку на объект.
ВС>Это, по моему мнению, предпочтительней.
А как из обертки получить нужный тип объекта? (а не просто void* или ISuperBase* )
Я представил себе это так (чем-то напоминает паттерн visitor"):
Обертка имеет интерфейс в виде набора методов, возращающих все возможные типы, но все они кроме одного возвращают 0 для конкретной реализации обертки. Обертку можно генерировать самим оборачиваемым объектом. Так что ли?
Здравствуйте, Ignoramus, Вы писали:
I>Здравствуйте, Владислав Сомов, Вы писали:
ВС>>Здравствуйте, Владислав Сомов, Вы писали:
ВС>>>б) Хранить целое — объект-обертку, содержащую ссылку на объект.
ВС>>Это, по моему мнению, предпочтительней.
I>А как из обертки получить нужный тип объекта? (а не просто void* или ISuperBase* )
I>Я представил себе это так (чем-то напоминает паттерн visitor"):
I>Обертка имеет интерфейс в виде набора методов, возращающих все возможные типы, но все они кроме одного возвращают 0 для конкретной реализации обертки. Обертку можно генерировать самим оборачиваемым объектом. Так что ли?
Ну подойдем немного с другой стороны...
Клиент вызывает какую-то функцию, в которую передает хендл.
В итоге эта функция реализуется через функциональность класса, который представляет хендл (я правильно понимаю?).
Значит нам нужно убедиться, что это хендл именно ожидаемого класса. После этого операции преобразования безопасны.
Чтобы обезопасить себя, как программиста сервера (библиотеки с хендлами), нужно сосредоточить все операции над хендлами в одном месте.
Обертка полезна для реализации общей функциональности. Например, подсчет ссылок на хендлы, закрытие хендлов и прочее.
On Tue, 06 Dec 2005 13:07:08 -0000, Ignoramus <18039@users.rsdn.ru> wrote:
> Для сопряжения С++ библиотеки и VB программы решил для представления объектов С++ использовать хендлы и процедурно-ориенторованный API (подобно WinAPI). Хендлы предполагаю хранить в ассоциативном массиве, в парах целое число — объект. > > Проблема в том, что объекты могут быть разных типов (классов). Варианты решения: > > 1) Поддерживать несколько таблиц хендлов — каждого типа отдельно, но тогда кол-во функций в API комбинаторно возрастает. > > 2) Различать тип объекта по хендлу. Например, разбить весь диапазон возможных значений хендлов на зарезервированные интервалы, и по интервалу определять тип, после чего делать соответствующий reinterpret_cast. Немного коряво и хаковато, зато типы могут быть совершенно независимы. (reinterpret_cast конечно хак, но система хендлов вообще — хак с точки зрения С++, а альтернативы ей я не вижу). > > 3) Наследовать все классы от одного интерфейса. Однако, если классы слишком разные, в этом обшем предке может вообще не оказаться полиморфных методов. Придется как-то даункастить, а этого хотелось бы избежать. > > Какие решения практикует all?
Слишком сложно ты напридумывал.
Делаем просто.
// api.h
// c-style apistruct handle;
handle* create_foo();
handle* create_bar();
long foo_fun(handle*);
long bar_fun(handle*);
// api.cpp#include"api.h"struct handle
{
virtual ~handle() {}
};
struct foo : handle
{
long fun();
};
struct bar : handle
{
long fun();
};
handle* create_foo()
{
return new (nothrow) foo;
}
long foo_fun(handle* h)
{
if(foo* p = dynamic_cast<foo*>(h))
return p->fun();
else
return E_BAD_HANDLE;
}
On Wed, 07 Dec 2005 07:39:23 -0000, Владислав Сомов <41483@users.rsdn.ru> wrote:
[]
> Боюсь, этого будет недостаточно. Вот пример:
Недостаточно для чего?
>
[]
>
Пример неудачен т.к. dynamic_cast<> не предназначен для проверки валидности указателей, использование его в качестве такого инструмента ошибочно.
Если необходимо обезопаситься от передачи невалидных указателей в API, что довольная редкая задача, придется хранить выданные указатели в какой-либо ст-ре данных и сверять их в вызове.
Здравствуйте, MaximE, Вы писали:
ME>Недостаточно для чего?
Для проверки валидности указателя.
ME>Пример неудачен т.к. dynamic_cast<> не предназначен для проверки валидности указателей, использование его в качестве такого инструмента ошибочно.
А такая проверка нужна.
ME>Если необходимо обезопаситься от передачи невалидных указателей в API, что довольная редкая задача, придется хранить выданные указатели в какой-либо ст-ре данных и сверять их в вызове.