У меня есть общая проблема написать оболочку C ++ для библиотеки C… мое основное хранилище — указатели C-Struct, которые всегда представляют класс C ++, содержащий только ОДИН данные поданы.
class MyClassC {
struct MyStructS * hdl
...
}
создание всех конструкторов, статических и методных функций — это НЕ проблема … моя проблема дизайна прямо сейчас … я должен использовать значение дизайн класса или указатель Классный дизайн.
значение класс имеет ОДИН в МНОГО отношения между MyStructS а также MyClassC
MyClassC myMethod () {
...
return MyClassC(struct MyStructS *...);
}
Разрушитель значение класс никогда свободно указатель struct MyStructS и в основном пусто
Разрушитель значение является статический или же метод в основном называется Дестри или же удалять
MyClassC::delete() {
DestroyMyPointer(&hdl)
}
...
MyClassC obj = {...};
...
obj.delete();
...
значение класс является аргументом методов а значение также:
some_proc_or_method (MyClassC arg1, MyClassC arg2, …) {
...
}
и есть другой вопрос:
как создать аргументы по умолчанию для значение классовый аргумент?
some_proc_or_method (MyClassC arg1, MyClassC arg2 = MyClassC {...} ???? ) {
...
}
указатель класс имеет ОДИН в ОДИН отношения между MyStructS а также MyClassC
MyClassC* myMethod () {
...
return this or getThisFrom(myStructS_pointer)
}
Разрушитель указатель класс всегда свободно указатель struct MyStructS
~MqClassC () {
DestroyMyPointer(&hdl)
}
...
MyClassC* obj = new MyClassC(...);
...
delete obj;
...
Я бы выбрал вариант 3: тонкая обертка, которая в первую очередь определяет правильность владения. Код C уже полезен в C ++. Единственная реальная выгода, которую можно получить при обёртывании — это получить семантику владения право. Оба ваших подхода пытаются возложить бремя отслеживания прав собственности на пользователя вашего API. Это не полезная оболочка, она просто добавляет лишний слой косвенности. Ваши клиенты по-прежнему должны учитывать внутреннюю часть C API, чтобы быть эффективными.
Вместо этого я предлагаю вернуть интеллектуальный указатель с четкой семантикой владения. Напишите несколько встроенных бесплатных функций, которые принимают умный указатель и перенаправляют на C API. Конечным результатом является то, что у вас есть почти тот же API (меньше кривой обучения) с семантикой владения C ++. Это выигрыш, и результат будет менее громоздким.
#include <memory>
#include <CLibAPI.h>
namespace CPPWrapC {
namespace detail {
struct DestroyMyPointer {
void operator()(MyStructS *hdl) {
::DestroyMyPointer(&hdl);
}
};
}
using Handle = std::unique_ptr<MyStructS, detail::DestroyMyPointer>;Handle myMethod() {
MyStructS *ret = /* init it */;
return Handle{ret};
}
inline void some_proc_or_method(Handle const& hdl) {
c_lib_some_proc_or_method(hdl.get());
}
}
Итак, теперь у вас есть простая оболочка, которая поддерживает дескрипторы с семантикой единого владельца. Именно то, что вы хотели, я думаю. И использовать его почти так же, как использовать оригинальный упакованный API, поэтому клиенты могут использовать все, что они знают о библиотеке C, для работы.
И это может служить трамплином. Теперь у вас есть тип C ++, который вы можете включить в качестве члена для дальнейшего переноса.
Других решений пока нет …