使用C和PHP-CPP开发PHP扩展:高级
使用C 和PHP-CPP开发PHP扩展:高级主题和最佳实践
关键要点
- 使用C 和PHP-CPP开发PHP扩展涉及高级主题,例如返回“this”指针、返回复杂对象指针、公开
__toString
魔术方法、链接成员函数调用以及PHP中的异常抛出和处理。 - 对于需要在未来用于非PHP项目的软件、数据结构或算法的项目,或者需要使用尚未作为PHP扩展提供的工具或库的项目,PHP-CPP库是理想的选择。它还提供C/C 代码的性能优势,同时保持结构化、面向对象的代码,便于理解和维护。
- PHP-CPP库可用于个人和商业项目。但是,虽然库本身是免费的,但可能需要时间和资源来学习如何有效地使用它并维护PHP扩展。
- 使用C 进行PHP扩展开发的常见挑战包括正确管理内存、处理错误和异常以及PHP和C 之间的接口。可以通过深入了解PHP和C 、使用良好的编程实践以及利用PHP-CPP提供的功能和工具来克服这些挑战。
在我之前的文章中,我介绍了使用C (第一篇文章和第二篇文章)创建PHP扩展的PHP-CPP库。在后一篇文章中,我演示了使用Complex类进行复数运算的编写PHP扩展的面向对象方面。
该介绍并不完整,因为该文章的主要重点更多地放在演示PHP-CPP的面向对象能力上,而不是面向对象的实现细节上。
在本文中,我们将进一步深入研究Complex库的开发,添加更多成员函数,并解决使用PHP-CPP编写具有面向对象功能的PHP扩展中的一些高级主题:
- 返回this指针;
- 返回Complex对象指针,即Complex *;
- 公开
__toString
魔术方法; - 链式成员函数调用;
- 抛出异常并在PHP中处理它
完整的Complex库源代码以及测试PHP脚本位于此Github存储库中。
让我们开始吧。
准备工作
在第一篇文章中解释了准备环境的整个过程。
在C 中返回this指针
如第二篇文章所述,我们使用成员函数对复数执行各种数学运算。在此演示中,我们将实现四个这样的函数:add、sub、mul和div。我将首先解释前三个。div函数涉及异常处理,稍后将讨论。
让我们看一下mul函数(用于乘法)。add和sub函数大致相同。
Php::Value add(Php::Parameters ¶ms) { Php::Value t = params[0]; Complex *a = (Complex *) t.implementation(); r += (double) a->getReal(); i += (double) a->getImage(); return this; }
注意:在本文中,我将不介绍一些之前讨论过的基本主题,例如修改Makefile和ini文件、注册成员函数、类和命名空间等。请参考前面的部分了解这些内容。
将this指针从C 返回到PHP很简单。在这个C 函数内部,this指针(作为Complex *类型)可以作为Php::Value类型返回到PHP。转换不会丢失任何对象信息。它也不需要显式类型转换。
返回Complex对象指针
返回this通常意味着对象本身已更改。但在某些情况下,我们可能希望返回一个新对象并保持“当前”对象(调用对象)不变。
在我们的Complex类中,我们有一个这样的函数,它返回给定复数的共轭数(a bi变为a-bi)。
Php::Value add(Php::Parameters ¶ms) { Php::Value t = params[0]; Complex *a = (Complex *) t.implementation(); r += (double) a->getReal(); i += (double) a->getImage(); return this; }
这里的关键点是,我们必须使用Php::Object将我们的Complex *对象显式转换为Php::Object,因此当该对象稍后由PHP脚本解析时,可以正确保留类信息并保持其可访问性。
此函数的第一个参数是类类型,在本例中为trComplex。我使用此名称是因为我已将此类(“Complex”)包装到单独的命名空间(“tr”)中。
第二个参数是要传回的对象。
返回新的类实例比只返回this指针要棘手一些,但只要您阅读了文档并找到了正确的部分,仍然是可以管理的。有关更多用法示例,您可能需要阅读PHP-CPP官方文档中的这一部分。
公开__toString魔术方法
在我们的类中,有一个__toString
函数,它以更易读的方式打印复数,例如:1 2i。在我之前的文章中,此函数未公开(或在PHP-CPP术语中“注册”),但仍然可以从PHP内部调用。但是,为了使此函数在我们应用一些数学运算(例如“echo $a->add($b)->sub($c)”)后能够在Complex对象上调用,我们需要在已编译的扩展中显式注册它:
Php::Value conjugate() { Complex *t = new Complex(); t->r = r; t->i = -i; return Php::Object("tr\Complex", t); }
我们在PHP-CPP存储库中提交的问题Issue #150详细讨论了我们必须这样做的原因。
链式成员函数调用
必须在此类中实现的一件事是能够链接成员函数,以便我们可以进行如下计算:$a->add($b)->sub($c)。结果仍然应该能够调用其成员函数。
这是通过上述方法完成的,即返回this指针到PHP。但是,较旧的PHP-CPP库在取消引用对象时存在错误,如果链接方法调用,则会创建“段错误”。
已提交问题(#151),并提交了包含PHP-CPP源代码补丁的提交。如果您使用的是旧版本的PHP-CPP库来编译PHP-CPP库和您自己的库,请更新PHP源代码并重新编译和重新安装PHP-CPP库和您的库。
如提交摘要所解释:
complex.method("__toString", &Complex::__toString);
我很高兴我自己的项目工作可以帮助我使用的库变得更好。
异常抛出和PHP中的处理
我们的Complex类中还有两个函数可能会将异常抛回PHP进行处理:div和phi。前者执行除法运算,后者返回复数的角度,如其替代表示形式极坐标表示法(r,θ)所示。
如果将复数作为参数(或调用者)传递,但其实部和虚部为0,则这两个操作都可能失败。对于这两个操作,我们需要进行异常处理。请记住,我们要在C 代码中抛出异常,而PHP脚本将捕获异常并进行必要的处理:
Php::Value add(Php::Parameters ¶ms) { Php::Value t = params[0]; Complex *a = (Complex *) t.implementation(); r += (double) a->getReal(); i += (double) a->getImage(); return this; }
在PHP脚本中,我们像这样捕获此异常:
Php::Value conjugate() { Complex *t = new Complex(); t->r = r; t->i = -i; return Php::Object("tr\Complex", t); }
上面的代码段将显示如下文本行:
complex.method("__toString", &Complex::__toString);
很简单,对吧?在我们的扩展中构造的C 异常被传回PHP并被正确捕获。此外,我们可以像处理其他PHP代码抛出的原生PHP异常一样操作异常!
测试所有函数
最后,我们可以通过make && sudo make install
为我们的PHP安装编译和安装complex.so扩展。如果一切顺利,我们可以通过在终端中发出以下命令来验证扩展的安装:
<code>修复问题#151,链式方法调用无法正常工作…… ……因为每个对象的引用计数未正确更新,这导致即使对象已分配给不同的变量,该对象也会被销毁。</code>
终端应该显示一行显示“/etc/php5/cli/conf.d/complex.ini”,我们可以确定我们的扩展已安装并准备由任何PHP脚本调用。
注意:如果我们检查此扩展的Makefile,我们将看到我们正在将此PHP扩展安装到其CLI环境中。如果我们想安装此扩展以便Apache加载它,我们更改以下行:
Php::Value div(Php::Parameters ¶ms) { Php::Value t = params[0]; Complex *b = (Complex*) t.implementation(); double t1 = b->mod() * b->mod(); if (t1 == 0) throw Php::Exception("Division by zero"); double tr = r * (double) (b->getReal()) + i * (double) (b->getImage()); double ti = i * (double) (b->getReal()) - r * (double) (b->getImage()); r = tr / t1; i = ti / t1; return this; }
此扩展的测试PHP脚本如下所示,并带有一些注释:
$a=new tr\Complex(1,2); $c=new tr\Complex(); //$c实际上是0+0i try { $res=$a->div($c); } catch(Exception $e) { echo "Caught exception: ".$e->getMessage()."\n"; } }
所有测试脚本都应该正确运行,并且异常被正确捕获。
结论
这总结了我关于使用C 构建PHP扩展的这个强大库的3篇文章系列。我们介绍了基础知识、面向对象方面以及面向对象编程中的一些高级主题。我们还帮助PHP-CPP有所改进。
我们还能用PHP-CPP做什么?我将引用几行我从Emiel Bruijntjes(PHP-CPP的合著者)收到的电子邮件通信:
如果您正在从事一个项目,并且具有以下一个或多个要求,则PHP-CPP库是理想的选择: – 您正在处理软件/数据结构/算法,并且您希望确保将来您的软件也可以用于非PHP项目。 – 您想使用尚未作为PHP扩展提供的工具或库。 – 您希望获得C/C 代码的更好性能(与PHP相比),但您还想构建结构化、面向对象的代码,以便其他开发人员/同事易于理解和维护。
可能性是巨大的:框架(如Phalcon)、模板语言(如Smarty或Twig)等等。
请留下您的评论和观点,让我们知道您使用此库做了什么!
使用C 开发PHP扩展的常见问题解答
使用C 开发PHP扩展的好处是什么?
使用C 开发PHP扩展具有多种好处。首先,它允许您在PHP应用程序中利用C 的强大功能和灵活性。这可以提高性能,尤其是在计算密集型任务中。其次,它提供了一种在PHP环境中重用现有C 代码的方法,这可以节省大量的开发时间和精力。最后,它使您能够创建自定义PHP扩展,这些扩展可以扩展PHP的功能并提供标准PHP库中不可用的功能。
如何开始使用C 进行PHP扩展开发?
要开始使用C 进行PHP扩展开发,您需要对PHP和C 编程语言都有基本的了解。您还需要安装PHP开发环境和C 编译器。安装这些先决条件后,您可以开始用C 编写PHP扩展。网上有很多资源可用,包括教程和示例代码,可以指导您完成此过程。
什么是PHP-CPP,它如何帮助PHP扩展开发?
PHP-CPP是一个用于使用C 开发PHP扩展的库。它提供了一组C 类和方法,简化了编写PHP扩展的过程。使用PHP-CPP,您可以以更自然和直观的方式编写PHP扩展,使用C 熟悉的语法和概念。这可以使开发过程更高效,并且减少错误。
我可以将PHP-CPP用于商业项目吗?
是的,PHP-CPP是开源软件,可用于个人和商业项目。但是,重要的是要理解,虽然库本身是免费的,但您可能需要投入时间和资源来学习如何有效地使用它以及维护您的PHP扩展。
使用C 进行PHP扩展开发的一些常见挑战是什么,我该如何克服它们?
使用C 进行PHP扩展开发的一些常见挑战包括正确管理内存、处理错误和异常以及PHP和C 之间的接口。可以通过深入了解PHP和C 、使用良好的编程实践以及利用PHP-CPP提供的功能和工具来克服这些挑战。
如何调试用C 编写的PHP扩展?
可以使用标准C 调试工具调试用C 编写的PHP扩展。此外,PHP-CPP提供了一些可以帮助调试的功能,例如异常处理和错误报告。
我可以将PHP-CPP与其他C 库一起使用吗?
是的,PHP-CPP可以与其他C 库一起使用。这使您可以利用PHP扩展中的各种C 功能。
如何提高用C 编写的PHP扩展的性能?
您可以通过使用高效的算法和数据结构、最大限度地减少内存使用以及优化C 代码来提高PHP扩展的性能。此外,PHP-CPP提供了一些可以帮助提高性能的功能,例如直接访问PHP变量和函数。
我可以为PHP-CPP项目贡献代码吗?
是的,PHP-CPP项目是开源的,欢迎社区的贡献。您可以通过报告错误、建议新功能或提交补丁来贡献代码。
在哪里可以找到更多关于使用C 进行PHP扩展开发的资源?
网上有很多资源可用于学习使用C 进行PHP扩展开发。这些资源包括教程、示例代码、文档和论坛。此外,PHP-CPP网站提供了大量关于使用该库的信息和资源。
以上是使用C和PHP-CPP开发PHP扩展:高级的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

会话劫持可以通过以下步骤实现:1.获取会话ID,2.使用会话ID,3.保持会话活跃。在PHP中防范会话劫持的方法包括:1.使用session_regenerate_id()函数重新生成会话ID,2.通过数据库存储会话数据,3.确保所有会话数据通过HTTPS传输。

PHP8.1中的枚举功能通过定义命名常量增强了代码的清晰度和类型安全性。1)枚举可以是整数、字符串或对象,提高了代码可读性和类型安全性。2)枚举基于类,支持面向对象特性,如遍历和反射。3)枚举可用于比较和赋值,确保类型安全。4)枚举支持添加方法,实现复杂逻辑。5)严格类型检查和错误处理可避免常见错误。6)枚举减少魔法值,提升可维护性,但需注意性能优化。

SOLID原则在PHP开发中的应用包括:1.单一职责原则(SRP):每个类只负责一个功能。2.开闭原则(OCP):通过扩展而非修改实现变化。3.里氏替换原则(LSP):子类可替换基类而不影响程序正确性。4.接口隔离原则(ISP):使用细粒度接口避免依赖不使用的方法。5.依赖倒置原则(DIP):高低层次模块都依赖于抽象,通过依赖注入实现。

静态绑定(static::)在PHP中实现晚期静态绑定(LSB),允许在静态上下文中引用调用类而非定义类。1)解析过程在运行时进行,2)在继承关系中向上查找调用类,3)可能带来性能开销。

RESTAPI设计原则包括资源定义、URI设计、HTTP方法使用、状态码使用、版本控制和HATEOAS。1.资源应使用名词表示并保持层次结构。2.HTTP方法应符合其语义,如GET用于获取资源。3.状态码应正确使用,如404表示资源不存在。4.版本控制可通过URI或头部实现。5.HATEOAS通过响应中的链接引导客户端操作。

在PHP中,异常处理通过try,catch,finally,和throw关键字实现。1)try块包围可能抛出异常的代码;2)catch块处理异常;3)finally块确保代码始终执行;4)throw用于手动抛出异常。这些机制帮助提升代码的健壮性和可维护性。

匿名类在PHP中的主要作用是创建一次性使用的对象。1.匿名类允许在代码中直接定义没有名字的类,适用于临时需求。2.它们可以继承类或实现接口,增加灵活性。3.使用时需注意性能和代码可读性,避免重复定义相同的匿名类。
