C ++ приведение из void * в SomeClass * - PullRequest
0 голосов
/ 29 ноября 2011

Я работаю над библиотекой C ++, которая будет динамически загружаться (dlopen, dlsym ...) в программах на C ++ и C в качестве плагина.

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

void *creator(void *instance) {
    return new MyClass();
}

void destroyer(void *instance) {
    MyClass *_instance = static_cast<MyClass*>(instance);
    delete _instance;
}

Проблема в том, что этот тип не безопасен. Возможно ли быть безопасным здесь? (static_cast, dynamic_cast, reinterpret_cast ...)

Это важно, поскольку я намереваюсь создать оболочку C для каждого метода MyClass. Это позволило бы мне загрузить эту библиотеку в C-программу (что-то вроде переноса DBus C, которое можно использовать со стилем C или стилем C ++). Поэтому я бы сделал что-то вроде этого:

int MyClassAddInts(void *instance, int a, int b) {
    MyClass *_instance = static_cast<MyClass*>(instance);
    return _instance->addInts(a, b);
}

Пожалуйста, имейте в виду, что это всего лишь фиктивный пример.

Большое спасибо.

Ответы [ 4 ]

1 голос
/ 29 ноября 2011

Вы можете использовать std::map<void*, MyClass*>.Затем, если указатель не будет распознан, вместо неопределенного поведения вы получите ошибку типа «элемент не найден в карте».

1 голос
/ 29 ноября 2011

Не совсем.Весь смысл прохождения через интерфейс C состоит в том, что вы удаляете всю зависимость от любого ABI C ++, поэтому нет способа сохранить информацию о типах через нее «естественным» образом.

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

0 голосов
/ 29 ноября 2011

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

0 голосов
/ 29 ноября 2011

Вы можете получить некоторую меру безопасности типов, указав указатели API C на структуры в стиле C, которые, в свою очередь, содержат указатели на ваши объекты C ++. Тогда у вас будет больше контроля над указателями (при условии, что клиенты C не вмешиваются в структуры, что они, безусловно, не должны), и есть некоторая проверка типов также на стороне C. Что-то вроде:

struct MyClassHandle {
    void * ptr;
}

Тогда у вас есть довольно хорошая идея, что ptr изнутри MyClassHandle будет успешно приведен к MyClass *.

Но, как сказал Kerrek SB, вы не можете получить какую-либо безопасность типов, когда кастуете из void * - информации просто нет.

...