наследование — лучший способ открыть файлы HDF5 в переполнении стека

Я пытался найти способ обойти некоторые недостатки привязки HDF5 C ++. В настоящее время мой код заполнен блоками try / catch, подобными следующим:

H5::Exception::dontPrint();
H5::H5File *file = NULL;
try {
file = new H5::H5File(fname.c_str(), H5F_ACC_RDWR);
} catch(H5::FileIException &file_exists_err) {
file = new H5::H5File(fname.c_str(), H5F_ACC_TRUNC);
}

В этом не должно быть необходимости — все, что я хочу сделать, — это открыть файл для доступа на чтение / запись, и, если он не существует, создать его. Другая, более сложная проблема заключается в создании вложенной группы (например, «/ parent / group»), в которой родительская группа не обязательно существует. В Unix / Linux эквивалент будет

mkdir -p parent/group

Однако в привязках HDF5 C ++ создание группы, родительская группа которой не существует, вызывает исключение.

По этим причинам я был мотивирован для создания файла заголовка, который решает некоторые из этих распространенных проблем. Моей первой мыслью было просто создать набор функций, которые, например, будут принимать имя файла и режим доступа и возвращать объект H5 :: H5File, или принимать имя группы и возвращать объект группы. Однако я думаю, что это не совсем идеально, поскольку у программиста, который использует этот заголовочный файл, остается вызов «удалить» для возвращаемых объектов, хотя программист никогда не вызывает явно «новый» в своем собственном коде. Кажется, это требует утечек памяти.

Поэтому моей второй мыслью было создание набора производных классов из H5 :: H5File и H5 :: H5Group, с конструкторами, которые не выдают исключений, когда файл еще не существует или когда родительская группа группы еще не существует , Моя попытка получить производный класс файлов была следующей:

namespace H5Utils {

class H5File : public H5::H5File {
public:
H5File(std::string fname);
~H5File();
};

}

H5Utils::H5File::H5File(std::string fname)
try : H5::H5File(fname.c_str(), H5F_ACC_RDWR)
{
std::cerr << "Opened existing file." << std::endl;
} catch(H5::FileIException &file_exists_err) {
std::cerr << "File does not exist. Creating new file." << std::endl;
H5::H5File(fname.c_str(), H5F_ACC_TRUNC);
}

H5Utils::H5File::~H5File() { }

Проблема, с которой я сталкиваюсь, двояка. Во-первых, блок try / catch в конструкторе повторно генерирует исключение, созданное

H5::H5File(fname.c_str(), H5F_ACC_RDWR)

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

H5::H5File(fname.c_str(), H5F_ACC_TRUNC);

является правильным (то есть конструирует ли он родительский класс?) Есть ли способ, чтобы производный класс ловил исключения в конструкторе базового класса, а затем вызывал другой конструктор для базового класса?

В более общем плане, может ли кто-нибудь придумать лучший / более элегантный способ устранения этих недостатков привязок HDF5 C ++?

8

Решение

Я предпочитаю вашу первоначальную идею создать несколько простых вспомогательных функций — это будет проще и минимизирует объем кода, который вам придется писать и документировать. Кроме того, чтобы обеспечить правильное управление памятью, вы можете использовать shared_ptr,

Вот простая функция-оболочка, эквивалентная вашему первоначальному примеру:

// a typedef for our managed H5File pointer
typedef std::shared_ptr<H5::H5File> H5FilePtr;

// create or open a file
H5FilePtr create_or_open(const std::string& fname)
{
H5::Exception::dontPrint();
H5::H5File* file = 0;

try {
file = new H5::H5File(fname.c_str(), H5F_ACC_RDWR);
} catch(const H5::FileIException&) {
file = new H5::H5File(fname.c_str(), H5F_ACC_TRUNC);
}

return H5FilePtr(file);
}
7

Другие решения

Однако в привязках HDF5 C ++ создание группы, родительская группа которой не существует, вызывает исключение.

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

#include "hdf5.h"
int main (void){
hid_t lcpl, file_id, group_id;
herr_t status;
unsigned flag=1;

lcpl = H5Pcreate(H5P_LINK_CREATE);
status = H5Pset_create_intermediate_group(lcpl, flag);
file_id = H5Fcreate("nested_groups.h5",  H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
group_id = H5Gcreate( file_id, "/foo/bar/bop", lcpl, H5P_DEFAULT, H5P_DEFAULT );

H5Pclose(lcpl);
H5Gclose(group_id);
H5Fclose(file_id);

return status;
}
3

По вопросам рекламы [email protected]