Привет пекари. Юзает ли кто-нибудь следующий прием в интерфейсах в своим либам?
Имеем структуру
struct Object
{
int somethingUseful;
....
int somethingUseful_n;
};
И хотим передать на вызывающую сторону этот объект. Передать объект из проги на С\С++ в другую прогу на С\С++ не проблема. Но если делаем библу под другие языки возможности передать структуру нет. Как быть? Передаем такую байду
int CreateObject()
{
Object * obj = new Object;
...
return reinterpret_cast<int>( obj );
}
На выходе получаем исковерканный указатель представленный четырьмя байтами инта( да, я знаю что инт может быть другого размера ). В интерфесных функциях юзаем следующую приблуду
void DoSomething( int object )
{
Object * obj = reinterpret_cast<Object*>( object );
// do something useful
}
И вот тут вырисовывается жирный минус этого подхода: нет гарантии того что "object" реально указатель на Object. Как быть?
Таки есть простой способ проверки правильности объекта.
Обновляем нашу структуру.
struct Object
{
volatile int dogTag;
int somethingUseful;
....
int somethingUseful_n;
};
volatile нужен чтобы компилятор не баловался с этой переменной во время оптимизации.
Правим создание объекта
#define DOG_TAG ( 0xDEADBEEF )
int CreateObject()
{
Object * obj = new Object;
obj->dogTag = DOG_TAG;
...
return reinterpret_cast<int>( obj );
}
Ну и нашу функцию делающую что-то с объектом.
void DoSomething( int object )
{
Object * obj = GetObjectByHandle( object );
// do something useful
}
Где GetObjectByHandle( object )
Object * GetObjectByHandle( int object )
{
Object * obj = reinterpret_cast<Object*>(object);
if( obj->dogTag == DOG_TAG )
return obj;
return 0;
}
В итоге не нужно создавать кэш всех объектов. Проверка dogTag простой способ проверки валидности объекта.
Пинайте ногами сей метод.