E_FAIL或S_FALSE,哪个更适合表示没有这样的属性?

Che*_* OT 5 c++ api winapi interface

我有一个图像检测模块,封装为COM模块.我导出的Key/Value GetterAPI,如:GetImageAttr(UINT key, void* pValue);.我们的产品可能或可能不会在图像上附加特殊结构,因此我的客户可以通过此API查询特定结构.

可能的用法如下:

ImageSpecialAttribute attr = {};
HRESULT hr = pImageDetector->GetImageAttr(IMAGE_SPECIAL_ATTRIBUTE, (void*)&attr);
Run Code Online (Sandbox Code Playgroud)

S_OK如果图像具有这样的附着结构,则返回是微不足道的.但如果没有,我应该返回E_FAIL还是S_FALSE?

  1. S_FALSE:一切都很好,只是图像没有这样的可选属性.

    • 强制用户检查hr == S_OK
    • 查询没有这种可选属性的图像不是错误.
  2. E_FAIL:不!出了点问题.您不应该查询此密钥.

    • 客户可以通过FAILED轻松检查(小时)
    • 使用此密钥查询此不存在的值是一个错误.

更新,(感谢Remy Lebeau)

  1. HRESULT_FROM_WIN32(ERROR_NOT_FOUND):不!没有这样的元素/属性.

    • 客户可以通过FAILED轻松检查(小时)
    • 虽然它代表一个错误,但用户仍然可以通过检查知道其含义hr.

Rem*_*eau 7

S_FALSE是成功值,而不是错误值。许多 Microsoft 自己的 COM APIS_FALSE在方法本身成功但请求的数据不可用或请求的操作未执行时返回。微软的文档中提到了这一点:

COM 中的错误处理

所有带有前缀“E_”的常量都是错误代码。常量 S_OK 和 S_FALSE 都是成功代码。可能 99% 的 COM 方法在成功时返回 S_OK;但不要让这个事实误导你。方法可能会返回其他成功代码,因此始终使用SUCCEEDEDFAILED宏测试错误。
...
成功代码 S_FALSE 值得一提。一些方法使用 S_FALSE 来粗略地表示不是失败的否定条件。它还可以表示“无操作”——方法成功了,但没有效果。例如,CoInitializeEx如果您从同一线程第二次调用该函数,则该函数返回 S_FALSE。如果您需要在代码中区分 S_OK 和 S_FALSE,则应直接测试该值,但仍使用FAILEDSUCCEEDED来处理其余情况...

我建议您遵循相同的约定,例如:

HRESULT hr = pImageDetector->GetImageAttr(IMAGE_SPECIAL_ATTRIBUTE, (void*)&attr);
if (SUCCEEDED(hr))
{
    if (hr != S_FALSE)
    {
        // use attribute as needed...
    }
    else
    {
        // attribute not found...
    }
}
else
{
    // error...
}
Run Code Online (Sandbox Code Playgroud)

如果您真的想为不存在的属性返回错误代码,我建议您HRESULT为该特定条件定义一个自定义,例如:

#define E_ATTR_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 1)
Run Code Online (Sandbox Code Playgroud)

或者:

#define E_ATTR_NOT_FOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
Run Code Online (Sandbox Code Playgroud)

然后你可以将该错误返回给调用者,例如:

HRESULT hr = pImageDetector->GetImageAttr(IMAGE_SPECIAL_ATTRIBUTE, (void*)&attr);
if (SUCCEEDED(hr))
{
    // use attribute as needed...
}
else if (hr == E_ATTR_NOT_FOUND)
{
    // attribute not found...
}
else
{
    // error...
}
Run Code Online (Sandbox Code Playgroud)

COM 没有为“未找到”条件定义标准化错误 HRESULT 代码(HRESULT_FROM_WIN32(ERROR_NOT_FOUND)将是最接近的标准等价物)。