Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > C++

Ответ
 
Опции темы
Старый 08.04.2014, 21:30   #1
mr.DIMAS
Дэвелопер
 
Аватар для mr.DIMAS
 
Регистрация: 26.12.2006
Адрес: Санкт-Петербург
Сообщений: 1,572
Написано 547 полезных сообщений
(для 1,540 пользователей)
Dog tag

Привет пекари. Юзает ли кто-нибудь следующий прием в интерфейсах в своим либам?

Имеем структуру

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 простой способ проверки валидности объекта.

Пинайте ногами сей метод.
__________________

(Offline)
 
Ответить с цитированием
Старый 08.04.2014, 21:47   #2
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 979
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: Dog tag

Да уж попинать надо.
Это на костыль похоже.

Для межпроцессного взаимодействия используют возможности ос.
Наверняка по PID можно удостовериться в валидности самого процесса.
А чтобы удостовериться в валидности объекта нужно просто вызывать функцию, которая возвращает только этот тип объекта.
О вызовах самих функций нужно договориться, но лучше stdcall, так как это совпадает с winapi (раз win делается?).

Вообще чтобы решить задачу глобально нужно разработать формат или протокол, который должны соблюдать оба приложения.

Ежели речь идет об адресном пространстве одного процесса то тогда есть dll, которая сохраняет имена всех функций и тогда по их сигнатуре должно быть понятно что они делают.
(Offline)
 
Ответить с цитированием
Старый 08.04.2014, 23:13   #3
mr.DIMAS
Дэвелопер
 
Аватар для mr.DIMAS
 
Регистрация: 26.12.2006
Адрес: Санкт-Петербург
Сообщений: 1,572
Написано 547 полезных сообщений
(для 1,540 пользователей)
Ответ: Dog tag

Ок. Сужу поле действий: самопальная библа подключаемая к б3д. Как быть в таком случае?
__________________

(Offline)
 
Ответить с цитированием
Старый 09.04.2014, 00:21   #4
HolyDel
 
Регистрация: 26.09.2006
Сообщений: 6,035
Написано 1,474 полезных сообщений
(для 2,707 пользователей)
Ответ: Dog tag

Ок. Сужу поле действий: самопальная библа подключаемая к б3д. Как быть в таком случае?
все нормально. отправляй как есть.
попробуй в какой нибудь FreeEntity передать мусор.

ну если уж совсем запарываться - то делай set на указатель. при создании объекта указатель в set пуляй, при удалении изымай, при обращении проверяй.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
mr.DIMAS (09.04.2014)
Старый 09.04.2014, 00:52   #5
mr.DIMAS
Дэвелопер
 
Аватар для mr.DIMAS
 
Регистрация: 26.12.2006
Адрес: Санкт-Петербург
Сообщений: 1,572
Написано 547 полезных сообщений
(для 1,540 пользователей)
Ответ: Dog tag

Впрочем я считаю этот подход имеет право на жизнь в интерфейсах к библиотекам. Функциональный интерфейс подходит для большинства случаев, а кому не подходит тот городит свои обертки.
__________________

(Offline)
 
Ответить с цитированием
Старый 09.04.2014, 01:48   #6
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 979
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: Dog tag

Я думаю у Xors3D есть определенный опыт взаимодействия нативного кода с блицем - посмотри как там.

Во первых твою задачу нужно чётко разделять на межпроцессное взаимодействие и на взаимодействие в одном адресном пространстве.
Второе решается проще.

Недостаток твоего подхода:
а) Неудобство пользователя: ты его опускаешь до уровня Си. Если ты не сопроводишь хедером с тегами, то пользователю придется самому писать эти теги, по памяти, так что легко ошибиться.
б) Проблема отладки: ты просто передаешь набор байтов без какой либо дополнительной информации. К тому же передача происходит чтением/записью - что не является каким либо структурным разделением выполняемой программы. Если бы ты использовал функцию и Соглашение о вызовах, дебарег смог бы хотя бы построить фреймы на основе стека и как либо структурировать действия программы. Более того если язык у клиента и библиотеки одинаковый, то я щитаю кощунство не использовать хедер с сигнатурами функций, описанием классов и т.п. потому что это тебе дает возможность отлаживать уже на уровне этого языка, а не ассемблера и компилятор сможет проконтролировать кучу ошибок и обезопасить код.
в) Проблема платформы: вот представь что ты скомпилировал библиотеку где выравнивание по 16 байтам, а у твоего объекта 4 байтные поля, а клиент скомпилирован с 4 байтным выравниванием, в итогде будут неприятности. Если был бы хедер то можно было бы хотябы при описании класса указать как выравнивать. А если были бы функции то вообще не было бы проблем - там оговорено как располагать в стеке или в каких регистрах.
г) Проблема защищенности: ты передаешь непонятно что, а если это является объектом то теоретически еще и методы переданного объекта можно вызывать. Представь себе если ктонибудь подделает тег, перепишет метод, например джампом вызовет вредоносный код и всё испортит тебе в системе. Так что тут не обойтись без протокола который обеспечивает минимальную защиту.
(Offline)
 
Ответить с цитированием
Старый 09.04.2014, 12:04   #7
mr.DIMAS
Дэвелопер
 
Аватар для mr.DIMAS
 
Регистрация: 26.12.2006
Адрес: Санкт-Петербург
Сообщений: 1,572
Написано 547 полезных сообщений
(для 1,540 пользователей)
Ответ: Dog tag

Возможно я неправильно объяснил свою мысль в первом посте. Суть в том что пользователю библы мы отдаем только хендл объекта. А при передаче этого хендла обратно в библу нужно проверить - годен ли хендл. Для этого в каждой структуре есть определенная метка имеющая уникальное значение.

Вкратце: любая порождающая функция библы передает хендл. Остальные - принимают его с проверкой.

А вообще есть статья на эту тему
__________________

(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Samodelkin (09.04.2014)
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 23:39.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com