草庐IT

C++ API设计和错误处理

coder 2024-02-15 原文

我需要使用 .lib 文件 (MSVC) 编写 C++ API,它由几个从 Dll 公开的导出 C++ 类组成。从我对另一个问题的回答我了解到,如果 C++ API 是在一个 VC++ 版本(比方说 2010)中构建的,而客户端代码是在另一个 VC++ 版本中编写的,则导出的类方法不能使用异常。由于异常不能成为公共(public) API 接口(interface)的一部分,我正在寻找另一种错误处理策略。我的限制:我不想使用 COM,丰富的错误代码系统(如 HRESULT)对我来说还不够。我想要类似异常的类,其中包含错误代码、错误消息和我需要的任何其他信息。另外,我不想为每个 VC++ 版本单独构建。

我目前的做法如下。每个公共(public)类方法都返回枚举值(如 ErrorCode)。在方法失败的情况下,像 GetLastErrorInfo 这样的静态函数会返回指向 C++ 类(假设为 ErrorInfo)的指针,其中包含到达错误信息。 ErrorInfo 保存为特定于线程的数据,并包含来自当前线程中最后一次调用的错误信息。如果最后一个 API 调用成功,GetErrorInfo 返回 NULL。

考虑以下代码的异常(exception)情况:

try
{
    classPtr->DoSomething();
    cout << classPtr->GetData() << endl;
}
catch(const MyException& ex)
{
    cout << ex.GetErrorMessage() << endl;
    return;
}

无一异常(exception)是这样的:

ErrorCode result;
int data;
result = classPtr->DoSomething();
if ( result != Success )
{
    cout << MyClass::GetLastErrorInfo()->GetErrorMessage() << endl;
    return;
}
result = classPtr->GetData(data);
if ( result != Success )
{
    cout << MyClass::GetLastErrorInfo()->GetErrorMessage() << endl;
    return;
}
cout << data << endl;

这看起来不太好。类接口(interface)很乱:每个函数现在都有 ErrorCode 返回类型。返回值成为输出参数。有没有更好的方法,允许到达错误信息,并保持干净的公共(public) API 接口(interface)?

最佳答案

您可能忽略了一个简单的解决方案。唯一的限制是异常不能跨越模块边界。客户端代码自身抛出异常没有问题。因此,在 header 中提供一个内联函数,比如 CheckReturn(),它会抛出丰富的异常。

要获得灵感,请查看 COM IErrorInfo 接口(interface)及其关联的 _com_error class .他们解决了完全相同的问题。另请注意 MSVC 中可用的 #import 指令,它会自动生成进行调用并在失败返回值时抛出异常的小型包装函数。但是您不想使用 COM,所以它不能直接使用。

关于C++ API设计和错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9054223/

有关C++ API设计和错误处理的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  6. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  7. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  9. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

  10. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

随机推荐