热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

DelphiDLL类异常

如何解决《DelphiDLL类异常》经验,为你挑选了1个好方法。

我需要编写一个DLL,但这是我第一次(总有一个),我找到了一个解决这个文档的解决方案.我最终得到了这段代码:

library DLLFrazioni;

uses
  System.SysUtils,
  System.Classes,
  Fractions in 'Fractions.pas';

{$R *.res}

function getFraction(a: integer; b: integer): PChar; stdcall; overload;
var f: TFraction;
begin

 f := TFraction.Create(a, b);
 try
  Result := PChar(f.getFraction);
 except
  Result := PChar('NaN');
 end;

end;

function getFraction(a: PChar): PChar; stdcall; overload;
var f: TFraction;
begin

 f := TFraction.Create(a);
 try
  Result := PChar(f.getFraction);
 except
  Result := PChar('NaN');
 end;

end;

exports
 getFraction(a: integer; b: integer),
 getFraction(a: Pchar);

begin
end.

TFraction在Fraction.pas中有一个类,它有这个实现(如果需要):

type
 TFraction = class
  private
   number: double;
   num, den: integer;
   fraction: string;
   function hcf(x: integer; y: integer): integer;
  public
   //input num+den -> result is a fraction num/den
   constructor Create(numerator: integer; denominator: integer); overload;
   //input string 'num/den' -> result is a reduced num/den
   constructor Create(value: PChar); overload;
   function getFraction: string;
 end;

这里的一切都很简单.


我必须能够使用Delphi和C++(Visual Studio)加载这个DLL,但我怀疑我还没有用谷歌解决.正如你所看到的,我已经声明了另一个包含该类的单元,所以我可以将这两个东西分开.

我像往常一样在delphi DLL中使用stdcall.我有以下问题:

    我必须创建一个object(f: TFraction),因为我需要从中获取返回结果getFraction.我是否必须使用通常的try-finally语句来包围它?我认为try-except更合适,因为我想在运行时避免异常.

    如果我删除了try-except,当然会发生异常.在这种情况下,当我从Delphi/C++程序调用该函数时,我可以处理它.但这样安全吗?我可以允许dll引发异常吗?

Rob Kennedy.. 5

一个except块提供从一个完全不同的目的finally块.这绝不是选择一个而不是另一个的问题.使用满足需求的任何一种.如果你需要两者,那么使用两者.一个except块是用于处理错误.一个finally块是为保护资源.

您对except块的使用是正确的,以处理getFraction失败的情况.

您应该包含一个finally块来保护您分配的资源,即TFraction对象.你现在根本没有释放对象,所以你有内存泄漏.

不允许异常转义DLL函数.你不能假设调用者知道如何处理抛出的Delphi对象.

编写DLL是一种情况,它对您有编写C和使用Windows API的经验非常有帮助.如果您编写的DLL遵循您在Windows API中看到的相同模式,那么您就是一个良好的基础.您会注意到Windows API函数从不引发异常.它们总是返回一个状态值,可能带有错误代码.


您的代码中还有其他问题.特别是,当你的DLL函数终止时,你将返回一个指向一个字符串的指针,因此指针是陈旧的.再次,遵循Windows API的模型是有帮助的.API几乎从不返回字符串.相反,API函数接收缓冲区指针和长度,然后填充调用者提供的缓冲区.返回字符串的API 通常使用记录的API分配内存,然后指定调用者稍后应使用哪种内存管理函数来释放内存.

在您的情况下,您将返回指向未管理的内存的指针.编译器为您管理它,并且编译器无法看到您的函数的调用者仍然想要使用该内存,因此编译器会插入代码以释放您的字符串.



1> Rob Kennedy..:

一个except块提供从一个完全不同的目的finally块.这绝不是选择一个而不是另一个的问题.使用满足需求的任何一种.如果你需要两者,那么使用两者.一个except块是用于处理错误.一个finally块是为保护资源.

您对except块的使用是正确的,以处理getFraction失败的情况.

您应该包含一个finally块来保护您分配的资源,即TFraction对象.你现在根本没有释放对象,所以你有内存泄漏.

不允许异常转义DLL函数.你不能假设调用者知道如何处理抛出的Delphi对象.

编写DLL是一种情况,它对您有编写C和使用Windows API的经验非常有帮助.如果您编写的DLL遵循您在Windows API中看到的相同模式,那么您就是一个良好的基础.您会注意到Windows API函数从不引发异常.它们总是返回一个状态值,可能带有错误代码.


您的代码中还有其他问题.特别是,当你的DLL函数终止时,你将返回一个指向一个字符串的指针,因此指针是陈旧的.再次,遵循Windows API的模型是有帮助的.API几乎从不返回字符串.相反,API函数接收缓冲区指针和长度,然后填充调用者提供的缓冲区.返回字符串的API 通常使用记录的API分配内存,然后指定调用者稍后应使用哪种内存管理函数来释放内存.

在您的情况下,您将返回指向未管理的内存的指针.编译器为您管理它,并且编译器无法看到您的函数的调用者仍然想要使用该内存,因此编译器会插入代码以释放您的字符串.


推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • React项目中运用React技巧解决实际问题的总结
    本文总结了在React项目中如何运用React技巧解决一些实际问题,包括取消请求和页面卸载的关联,利用useEffect和AbortController等技术实现请求的取消。文章中的代码是简化后的例子,但思想是相通的。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
author-avatar
多米音乐_53913411
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有