2012-12-12 19 views
8

私は、HDF5 C++バインディングの欠点を回避する方法を考え出しています。現在、私のコードは次のようなのtry/catchブロックが散らばっている: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); 
} 

これは必要ありません - 私がやりたいすべての読み取り/書き込みアクセスのためのファイルを開くことであり、それはdoesnの場合それを作成するために存在しません。別の問題は、親グループが必ずしも存在しないネストされたグループ(「/ parent/group」など)を作成することです。 UNIX/Linuxでは、同等のは、その親グループが存在しない例外が発生しグループを作成し、HDF5 C++バインディングでは、しかし

mkdir -p parent/group 

だろう。

これらの理由から、これらの共通の問題のいくつかを扱うヘッダーファイルを作成する意欲がありました。私の最初の考えは、例えば、ファイル名とアクセスモードをとり、H5 :: H5Fileオブジェクトを返す、またはグループ名を取得してグループオブジェクトを返す一連の関数を単純に作成することでした。しかし、プログラマーが明示的に "new"を自分のコードで呼び出すことはないにもかかわらず、このヘッダファイルを使って返されたオブジェクトに対して "delete"を呼び出すプログラマーを残すため、これは理想的ではないと思います。これはメモリリークを求めているようです。

したがって、ファイルがまだ存在しないときに例外をスローしないコンストラクタを使用して、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); 

が正しい、私は2番目のコンストラクタそのことを確認していないということです次に、基本クラスのために別のコンストラクタを呼び出しますか?

さらに一般的に、HDF5 C++バインディングのこれらの欠点に対処するより優れた/よりエレガントな方法を考える人はいますか?

+0

"もう1つ、難しい問題は、親グループが必ずしも存在しないネストされたグループ(たとえば"/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

関連する問題