PHP扩展-使用std::string的全局类



我正在学习如何编写PHP扩展,遇到了一个在Interweb上找不到答案的问题。我正在尝试使用PHP扩展中的C++类,尽管它似乎可以在CLI中工作,但valgrind报告了问题。

我的全局设置如下:

ZEND_BEGIN_MODULE_GLOBALS(myext)
  MyClass *myClass;
ZEND_END_MODULE_GLOBALS(myext)

这个类被实例化为一个扩展全局如下:

static void myext_init_globals(zend_myext_globals *myext_globals TSRMLS_DC)
{  
  myext_globals->myClass = (MyClass*)pemalloc(sizeof(MyClass), 0);
  MyClass *myClass = new (myext_globals->myClass) MyClass();
}

使用释放

static void myext_destroy_globals(zend_myext_globals *myext_globals TSRMLS_DC)
{
  pefree(myext_globals->myClass, 0);
}

MyClass.h:

class MyClass
{
  private:
    std::string strSomeText;
  public:
    MyClass();
    ~MyClass();
};

MyClass.cpp:

MyClass::MyClass()
{
  strSomeText = "ABC"; // <-- this causes valgrind errors!
}

我发现,如果我可以将strSomeText作为一个静态成员变量,那么valgrind不会报告任何错误。

此外,如果我试图在MyClass构造函数中分配内存,然后在MyClass析构函数中删除或释放内存,valgrind会再次报告泄漏。

理想情况下,我希望能够获取"任何ol类"并使用它,而不必对其进行重大更改,只需将其作为PHP全局扩展即可。

更新:我的问题是,如何使用一个"泛型"C++类来使用std::string之类的东西,或者分配/取消分配内存(在构造函数/析构函数或成员方法中)?我发现,如果我在MyClass中包含php.h,然后使用emalloc/pemalloc分配内存,然后使用efree和pefree取消分配内存,那么一切都正常,valgrind没有报告内存泄漏。然而,这并不理想。必须有一种方法可以使用"通用"C++类(即,不必重构为对PHP扩展友好的类)作为PHP全局扩展(如我上面的示例所示)。

为什么要使用pealloc/pefree?我不知道如何调用myClass的析构函数?试试这个,没有ZEND_END_MODULE_GLOBALS:

std::unique_ptr<MyClass> myClass;

PHP_MINIT_FUNCTION(myext)
{  
  myClass = std::unique_ptr<MyClass> (new MyClass);
}
PHP_MSHUTDOWN_FUNCTION(myext)
{
  myClass.reset();
}

在PHP模块中使用C++确实很棘手。在出现错误或HTTP请求中断的情况下,PHP函数调用永远不会返回。这会中断异常和析构函数调用。因此,最好将C++代码与PHP函数调用完全分离。PHP_MINIT_FUNCTION和PHP_MSHUTDOWN_FUNCTION保证在模块启动和退出时被调用。然而,PHP作为一个Apache模块可以创建一个伪版本的模块,然后才创建真正的模块。PHP_MINIT_FUNCTION和PHP_MSHUTDOWN_FUNCTION也被调用用于伪版本,因此您应该避免在此处分配巨大的对象和/或进行大量磁盘读/写等操作。

相关内容

  • 没有找到相关文章

最新更新