PHP扩展包装为C ++ [英] PHP extension wrapper for C++
问题描述
我是PHP的这一领域的新扩展,但我需要创建一个包装类的C ++到PHP。我目前使用PHP 5.2.13。我阅读了本文 http://devzone.zend .com / article / 4486-Wrapping-C-Class-in-a-PHP-Extension ,一个关于如何继续包装C ++类以与PHP Zend通信的教程,但它是写入到linux系统。你们有任何文章或建议,如何我可以继续写一个包装类与PHP沟通?
I am new in this area of writing extension for PHP, however I need to create a wrapper class for C++ to PHP. I am currently using PHP 5.2.13. I read this article http://devzone.zend.com/article/4486-Wrapping-C-Classes-in-a-PHP-Extension, a tutorial on how I could proceed to wrap C++ class to communicate with PHP Zend however it is written to for linux system. Do you guys have any article or advice on how I could proceed to write a wrapper class to communicate with PHP?
推荐答案
这正是我最近做的。你参考的教程是一个好的(这也是我的起点)。这是我遵循的基本过程包装我的类。假设你正在包装名为 Myclass 的C ++类:
This is exactly what I've been doing lately. The tutorial you referenced is a good one (it was my starting point as well). Here's the basic process I've followed for wrapping my classes. Say you're wrapping your C++ class named Myclass
:
创建 php_myclass.h :
#ifndef PHP_MYCLASS_H
#define PHP_MYCLASS_H
extern "C" {
#include "php.h"
}
// Include your C++ class definition
#include "Myclass.h"
// Here is the struct which will represent the PHP version of your Myclass.
// It simply includes a pointer to a Myclass and a zend_object for PHP to
struct myclass_object {
zend_object std;
Myclass *myclass;
};
// Here is whatever your PHP class is going to be called in the userspace (the PHP code)
#define PHP_MYCLASS_CLASSNAME "Myclass"
extern zend_class_entry *myclass_ce;
extern zend_object_handlers myclass_object_handlers;
zend_object_value myclass_create_handler(zend_class_entry *type TSRMLS_DC);
// Later, this will be the array full of your Myclass's method declarations
extern function_entry php_myclass_functions[];
#endif /* PHP_MYCLASS_H */
然后在 php_myclass.cpp :
#include "php_myclass.h"
zend_class_entry *myclass_ce;
zend_object_handlers myclass_object_handlers;
// I'm still a newb, but I think this is the function that handles memory management when
// the PHP class is deleted (goes out of scope, script ends, whatever)
void myclass_free_storage(void *object TSRMLS_DC)
{
myclass_object *obj = (myclass_object*)object;
delete obj->myclass;
zend_hash_destroy(obj->std.properties);
FREE_HASHTABLE(obj->std.properties);
efree(obj);
}
// And likewise I believe this handles, as the name implies, mem management
// when your Myclass is instantiated.
zend_object_value myclass_create_handler(zend_class_entry *type TSRMLS_DC)
{
zval *tmp;
zend_object_value retval;
// make room in memory for a new PHP Myclass object:
myclass_object *obj = (myclass_object*)emalloc(sizeof(myclass_object));
// fill that memory with 0s
memset(obj, 0, sizeof(myclass_object));
obj->std.ce = type;
// some magic stuff (no idea)
ALLOC_HASHTABLE(obj->std.properties);
zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy(obj->std.properties, &type->default_properties, (copy_ctor_func_t)zval_add_ref, (void*)&tmp, sizeof(zval*));
// make it so you can get an instance of this object in later code
retval.handle = zend_objects_store_put(obj, NULL, myclass_free_storage, NULL TSRMLS_CC);
retval.handlers = &myclass_object_handlers;
return retval;
}
// First, we define some argument info for methods that take arguments (if we have any)
// This one means, obviously, one argument:
ZEND_BEGIN_ARG_INFO_EX(php_myclass_one_arg, 0, 0, 1)
ZEND_END_ARG_INFO()
// This one two args, etc.
ZEND_BEGIN_ARG_INFO_EX(php_myclass_two_args, 0, 0, 2)
ZEND_END_ARG_INFO()
// Here's where you tell PHP what methods your Myclass PHP class has.
function_entry php_myclass_functions[] = {
// A special property at the end of this line for the constructor:
PHP_ME(Myclass,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
// Normal methods look like this:
PHP_ME(Myclass,methodNameNoArgs,NULL,ZEND_ACC_PUBLIC)
PHP_ME(Myclass,methodName1Arg,php_myclass_one_arg,ZEND_ACC_PUBLIC)
PHP_ME(Myclass,methodName2Args,php_myclass_two_args,ZEND_ACC_PUBLIC)
// Three magic NULL values, no idea why they have to go here.
{ NULL, NULL, NULL }
};
// And now, define each of those Myclass methods you just instructed PHP
// to expose to the userspace:
PHP_METHOD(Myclass, __construct)
{
Myclass *myclass = NULL;
zval *object = getThis();
// Create an instance of the class you're wrapping
myclass = new Myclass();
// Make object (which points to $this for your PHP object instance)
// an instance of the struct that represents your php class
myclass_object *obj = (myclass_object*)zend_object_store_get_object(object TSRMLS_CC);
// Set the internal Myclass of this to the instance of Myclass you just made
obj->myclass = myclass;
// Done.
}
PHP_METHOD(Myclass, methodNameNoArgs)
{
// Get the current instance of your PHP Myclass into myclass:
Myclass *myclass;
myclass_object *mo = (myclass_object*)zend_object_store_get_object(getThis() TSRMLS_CC);\
myclass = mo->myclass;
if (obj == NULL) {
// error checking
RETURN_NULL();
}
// Return the value of your myclass method using one of the RETURN_* macros
// Here we'll pretend this one returns boolean:
RETURN_BOOL(myclass->methodNameNoArgs());
}
PHP_METHOD(Myclass, methodName1Arg)
{
// Now, let's pretend your Myclass::methodName1Arg(int) takes an int
// and returns a std::vector (which you want to be an array)
long param;
// Get the current instance of your PHP Myclass into myclass:
Myclass *myclass;
myclass_object *mo = (myclass_object*)zend_object_store_get_object(getThis() TSRMLS_CC);\
myclass = mo->myclass;
if (obj == NULL) {
// error checking
RETURN_NULL();
}
// Here's how you parse parameters of your PHP method call.
// The second parameter is "l" for long int. Read the tutorials online for more
// on how to use this function.
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", ¶m) == FAILURE) {
RETURN_NULL();
}
// Get the real return value you want to translate for PHP
std::vector retval = myclass->methodName1Arg(param);
// Use the magic "return_value" (which is in every method behind-the-scenes)
// and initialize it to be a PHP array:
array_init(return_value);
// Loop through the vector and build the array:
for (std::vector::iterator i = retval.begin(); i != retval.end(); ++i) {
add_next_index_long(return_value, *i);
}
// done. return_value is always returned for you.
}
PHP_METHOD(Myclass, methodName2Args)
{
// "Left as an exercise for the reader" is coder slang for
// "I *really* don't feel like typing anymore." :)
}
我希望这个示例代码编译,或至少帮助。 :)它是一种仓促地从真正的工作代码我在这里,如果找到/替换打破了一些东西,至少你可能会得到一个想法,做什么。有很多遗漏的东西,请阅读Sara Golemon的关于 http://devzone.zend的三部分扩展教程。 com / article / 1021 了解更多。祝你好运。
I hope this example code compiles, or at least helps. :) It was sort of hastily put together from real working code I have here, and if the find/replaces broke something, at least you might get an idea of what to do. There's plenty that's left out of this, read Sara Golemon's three-part extensions tutorial on http://devzone.zend.com/article/1021 for more. Good luck.
这篇关于PHP扩展包装为C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!