std::string. Делать strdup? С остальными данными также или есть лучше способы?
Это слишком общий вопрос, делать надо по разному.
сишное api обычно не через strdup возвращает строки, а через параметры
Что касается плюсовых контейнеров, то да, придётся данные копировать в примитивные типы или в какие-то POD-структурки: std::string -> char* std::list -> LIST_HEADER + LIST_ENTRY (Windows only) Ну и так далее, надо просто найти/создать подходящие по смыслу обёрточки Если же это класс с реализацией, то можно в принципе создать экземпляр, а вернуть void*, который потом в приложении скастить к нужному типу (например, если из DLL надо получить что-то)
Зачем POD-ы. Я вообще вон писал код из серии типа MyLibInstance* CreateMyLibInstance(...); Ну и потом вызывал методы как-то через someMethod(mylibInstance, ...); что семантически было идентично mylibinstance->someMethod(...);
+ В Си вполне можно эмулировать ООП и даже полиморфизм с помощью структуры с полями и указателями на "методы". Только вот инициализацию и очистку придется делать ручками.
Можно, только я видел насколько много макросов для этого приходится городить
Што поделать: в Си шаблоны не завезли.
Дак а как строку вернуть из someMethod?
Просто берёшь и возвращаешь. RVO справится.
Это не то. Это, скорее, в тему перегрузки.
нет, женерик это как раз про шаблоны)
Если имеется ввиду просто вернуть std::string, то это не прокатит
Скорее всего си-апи не просто так нужен. Скорее всего вызывающий код не сможет правильно сделать деаллокейт строке, и будет беда
Почему? https://godbolt.org/z/19zdjd
Я так понимаю изначальный вопрос был «как мне завернуть С++ код в сишный» Я думаю это нужно для того, чтобы сделать шаред либу. Скорее всего это нужно чтобы юзать её из любого другого кода. Например с другим си-рантаймом А если это так, и вы вернёте объект из одного модуля (у которого си-рантайм один) И попытаетесь освободить память в другом модуле (с другим си-рантаймом) — то словите хип-карраптед
давай разбивать, анализировать
Обычно в DLL(или .SO) юзают паттерн "фабрика" для вытаскивания интерфейсов. Гляньте в тот же COM от Microsoft.
для этого есть mylib_free()
1) пример, 2) какая разница?
Дак если либа вернёт объект строки. память на строку удалится на деструкторе строки. А выделялась в другом модуле
сложные данные через опакуе, самое собой
я про сишное апи тут
Возвращай структуры с полями char* str, size, capacity...
Вроде бы эту проблему должен решить polymorphic allocator, но это не точно.
Без UB сложно сделать, но чаще всего так поступаю: int len = myfunc(NULL); str.resize(len); myfunc(&str[0]);
Не знаю, может быть 🙂 Тут главное понимать что если в каком-то модуле выделилась память — то в том же модуле должна и освободиться. Не знаю как polymorphic allocator эту проблему решит, но может как-то решит )
Я в своих проектах не перекладываю ответственность на PMR, а просто прибегаю к принципу "я тебя породил — я тебя и убью".
Что это что?
Ну дак тогда и из либы не получится вернуть std::string. Разве нет?
Да, я бы не стал так делать.
.data()? И дальше что хочешь делай. Хочешь копируй хочешь просто используй не изменяя конечно. Ну это так
1) errcode_t get_str(char* buf, size_t* buf_size); 2) Ты даёшь клиенту возможность самому управлять памятью
Если buf == NULL, то функция в buf_size возвращает размер, который нужен, чтобы поместить строку (если это возможно) + доп. проверки, если переданный buf_size < необходимого. Так обычно сишное апи делает
а если рассчитывать размер буфера заранее очень накладно, что тогда? я так понял функция может вернуть необходимое количество памяти для размещения строки
Обсуждают сегодня