PHP扩展包装为C ++ [英] PHP extension wrapper for C++

查看:110
本文介绍了PHP扩展包装为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆