TensorFlow 或者 Keras 保存的 Model 或者 Weight 都是 HDF5 文件, 当我们想用 C++ 实现加载 Model 或者 Weight 的时候, 就需要操作 HDF5 文件, 所以在这里做一个写 HDF5 文件的例子, 给大家参考一下
这个可以从网上下载自己编译, 但是 1.10.6 版本会缺少头文件 H5pubconf.h, 可参考 HDF5 CMake 生成 C\C++ 可用的 lib 文件和 dll 文件 或者直接下载我编译好的(包含 H5pubconf.h),
下载地址: C\C++ 读写 HDF5 所需头文件和库文件
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
#include "stdafx.h"
#include // 需要添加的头文件
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
添加完成之后, 会显示找不到头文件, 如下图, 没有关系, 因为我们还没有添加包含目录
4. 设置包含目录
包含目录设置完成之后, include 那一行就不会画红线了
6. 设置库目录
经过上面的设置之后, 基本就完成了, 下面开始填坑
#include "stdafx.h"
#include
#include
#define H5FILE_NAME "SDS.h5"
#define DATASETNAME "IntArray"
#define NX 5 /* dataset dimensions */
#define NY 6
#define RANK 2
int _tmain(int argc, _TCHAR* argv[])
{
hid_t file, dataset; /* file and dataset handles */
hid_t datatype, dataspace; /* handles */
hsize_t dimsf[2]; /* dataset dimensions */
herr_t status;
int data[NX][NY]; /* data to write */
int i, j;
/*
* Data and output buffer initialization.
*/
for(j = 0; j < NX; j++)
{
for(i = 0; i < NY; i++)
{
data[j][i] = i + j;
}
}
/*
* 0 1 2 3 4 5
* 1 2 3 4 5 6
* 2 3 4 5 6 7
* 3 4 5 6 7 8
* 4 5 6 7 8 9
*/
/*
* Create a new file using H5F_ACC_TRUNC access,
* default file creation properties, and default file
* access properties.
*/
file = H5Fcreate(H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
/*
* Describe the size of the array and create the data space for fixed
* size dataset.
*/
dimsf[0] = NX;
dimsf[1] = NY;
dataspace = H5Screate_simple(RANK, dimsf, NULL);
/*
* Define datatype for the data in the file.
* We will store little endian INT numbers.
*/
datatype = H5Tcopy(H5T_NATIVE_INT);
status = H5Tset_order(datatype, H5T_ORDER_LE);
/*
* Create a new dataset within the file using defined dataspace and
* datatype and default dataset creation properties.
*/
dataset = H5Dcreate2(file, DATASETNAME, datatype, dataspace,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
/*
* Write the data to the dataset using default transfer properties.
*/
status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
/*
* Close/release resources.
*/
H5Sclose(dataspace);
H5Tclose(datatype);
H5Dclose(dataset);
H5Fclose(file);
return 0;
}
先不管是什么意思, 生成解决方案看一下, 结果一生成, 整个人都不好了, 报了一堆错误
遇到 error LNK2019: 无法解析的外部符号 这样的错误, 作为一个 C++ 程序猿, 相信你已经遇到过千百次了, 意思就是找不到 lib 文件嘛, 那我们就把相关的 lib 文件(这里只需要 hdf5_D.lib, 带 D 表示调试版本)添加到 附加依赖项 里面
如果你不喜欢附加依赖项这样的方式, 你用以下的方式, 一样的效果
#include
#include
#ifdef _DEBUG
#pragma comment(lib, "hdf5_D.lib")
#else
#pragma comment(lib, "hdf5.lib")
#endif
最下面还有一个错误是 fatal error LNK1120: 1 个无法解析的外部命令, 这个要怎么解? 只需要增加一个预处理器定义H5_BUILT_AS_DYNAMIC_LIB 就好了
按 F5 运行看一下, 马上又有错误
这个问题很简单, 相信你也遇到过千百回了, 只需要将编译好的 dll 或者下载的 bin 目录中的 dll 复制到你的工程目录中的 Debug 或者 Release 文件夹下就可以了, 如果是调试就是 Debug, 不用全都复制, 因为现在只需要 hdf5_D.dll, 也可以将 hdf5_D.dll 所在目录添加到添加环境变量, 不过复制方便一点
完成后再运行, 就不会报错了, 黑色窗口一闪而过, 在工程目录下留下一个 SDS.h5 文件
现在你可以用 HDF5 View 之类的看一下里面写的是什么了, 打开之后就是代码里面写的那个二维数组
注意, HDF5 View 不能打开有中文路径的文件
具体代码中的每个函数是什么意思, 自己也能推敲出来吧, 或者到官网转一下
以上是 C语言版本的示例, C++版本示例可以在 hdf5-1.10.6\c++\examples 找到, 只是要注意附加依赖项要多一个
hdf5_cpp_D.lib 或者 hdf5_cpp.lib
完整的代码可下载 VS2015 x64 代码示例