2012-12-12 1 views
8

저는 HDF5 C++ 바인딩의 단점을 극복 할 수있는 방법을 모색하고 있습니다. - 내가하고 싶은 모든 읽기/쓰기 액세스를 위해 파일을 열 수 있습니다, 그것은 아무튼 경우C++에서 HDF5 파일을 여는 더 나은 방법

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); 
} 

이 필요는 없습니다 : 현재, 내 코드는 다음과 같은 시도/catch 블록에 산재되어 그것을 창조하기 위해 존재하지 않습니다. 더 까다로운 문제는 부모 그룹이 반드시 존재하지는 않지만 중첩 그룹 (예 : '/ parent/group')을 만드는 것입니다. 유닉스/리눅스에서 상응하는 부모가 그룹 존재하지 않는 예외를 발생 그룹을 창조하는 HDF5 C++ 바인딩에서 그러나

mkdir -p parent/group 

될 것입니다.

이러한 이유로 저는 이러한 공통적 인 문제를 다루는 헤더 파일을 만들려고했습니다. 필자의 첫 번째 생각은 단순히 파일 이름과 액세스 모드를 취하여 H5 :: H5File 객체를 반환하거나 그룹 이름을 가져 와서 그룹 객체를 반환하는 함수 집합을 만드는 것입니다. 그러나 프로그래머가 자신의 코드에서 "new"를 명시 적으로 호출하지 않더라도이 헤더 파일을 사용하는 프로그래머는 반환 된 객체에서 "delete"를 호출하는 프로그래머를 떠나기 때문에 이것이 이상적이라고 생각하지는 않습니다. 이것은 메모리 누출을 요구하는 것 같습니다.

따라서 두 번째 생각은 파일이 아직 존재하지 않을 때 예외를 throw하지 않는 생성자를 사용하거나 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) 

으로 생성 된 예외를 다시 throw하므로 프로그램은 여전히 ​​종료됩니다. 두 번째 문제는 기본 클래스 '생성자에서 파생 된 클래스 캐치 예외가 할 수있는 방법이 있나요 (즉 그것은 상위 클래스를 구성합니까?)

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

이 올바른지, 내가 두 번째 생성자가 확실하지 않다이다 , 다음 기본 클래스에 대해 다른 생성자를 호출?

더 일반적으로 HDF5 C++ 바인딩의 이러한 단점을 처리하는 더 좋고/더 우아한 방법을 생각할 수 있습니까?

+0

"부모 그룹이 반드시 존재하지는 않지만 중첩 된 그룹 (예 :"/ parent/group ")을 만드는 것이 더 까다로운 문제입니다. 유닉스/리눅스에서는 등가가 될 것입니다. "- 이것을 할 수있는 좋은 방법을 찾았습니까? –

+2

"/ parent/group/subgroup"과 같이 중첩 된 그룹 이름이 주어지면 먼저 "/ parent", "/ parent/group"및 "/ parent/group/subgroup"으로 분할 한 다음 각 순서대로 열어보십시오. 주어진 그룹이 존재하지 않는다면 (C++ API에서는'H5 :: FileIException'을 얻습니다), 생성하십시오. 나는 [이 문제를 다루는 몇몇 도우미 함수들] (https://github.com/gregreen/h5utils/blob/master/src/h5utils.cpp#L92)을 썼다. – Thucydides411

+0

최근에 같은 문제가 발생했습니다 http://stackoverflow.com/questions/35668056/test-group-existence-in-hdf5-c. 해결책 없음. 그것의 맨 위에, 나는 H5 :: Exception이 std :: exception ...에서 파생되지 않는다는 것을 주목했다. – eudoxos

답변

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); 
} 
3

의 HDF5 C++ 바인딩에서, 부모가 그룹 존재하지 않는 예외를 발생 그룹을 만들.

링크 생성 속성 목록을 create missing intermediate groups으로 설정할 수 있으며이 예외는 발생하지 않습니다.예 :

#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; 
} 
+0

이것은 C++로 작성하는 경우에도 C API를 사용하기위한 또 다른 인수입니다. 객체 지향 C++ API에는 많은 기능이 빠져 있으며 플래그를 설정하는 대신 예외를 던지기와 같은 일부 디자인 옵션은 상당히 성가시다. – Thucydides411