Geçenlerde PHP uzantıları yazmaya bakarak başladı ve ben C + + kullanarak bir uzantısı oluşturmak için bir başlangıç noktası açıklayan, this article okuyun. Ben özelleştirmek başladım, ben ayrı bir dosya içine bazı işlevleri bölmek için çalışan bir aksama çalıştırmak. Her şey derler ve sorunsuz bağlantılar, ama aslında uzantısı kullanmaya çalıştığınızda bir hata oluşur. Tam mesajı:
$ php -dextension=test.so -r "var_dump( new Test );"
php: symbol lookup error: /etc/php/ext/test.so: undefined symbol: _ZN9ContainerI4TestEC1EP17_zend_class_entry
Ben iki bilgisayar üzerinde çalıştı ve hem de aynı sorunu yaşayabilirsiniz. Ben Konteyner kurucu için gerçek uygulama bulamıyorum anlıyorum, ama doğru yerde aramak için nasıl bilmiyorum.
Ben buraya göndermeden önce ben olabildiğince kabartmak kadar kesip çalıştım, ama cruft bir sürü php interface kodu hala var. Aşağıdaki gibi kodu:
config.m4:
PHP_ARG_ENABLE(test,
[Whether to enable the "test" extension],
[ --enable-test Enable "test" extension support])
if test $PHP_TEST != "no"; then
PHP_REQUIRE_CXX()
PHP_SUBST(TEST_SHARED_LIBADD)
PHP_ADD_LIBRARY(stdc++, 1, TEST_SHARED_LIBADD)
PHP_NEW_EXTENSION(test, interface.cpp internals.cpp, $ext_shared)
fi
interface.h:
#ifndef INTERFACE_H_
#define INTERFACE_H_
#define PHP_TEST_EXTNAME "test"
#define PHP_TEST_EXTVER "0.1"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#endif
interface.cpp:
#include "interface.h"
#include "internals.h"
#include "php.h"
class Test {};
extern zend_module_entry test_module_entry;
zend_object_handlers test_object_handlers;
zend_class_entry *test_ce;
void test_free_storage(void *object TSRMLS_DC)
{
delete (Container<Test> *) object;
}
zend_object_value test_create_handler( zend_class_entry* classInfo TSRMLS_DC )
{
Container<Test> *obj = new Container<Test>( classInfo );
zend_object_value retval;
retval.handle = zend_objects_store_put(
obj, NULL, test_free_storage, NULL TSRMLS_CC
);
retval.handlers = &test_object_handlers;
return retval;
}
PHP_METHOD(Test, __construct)
{
Test* test = new Test;
Container<Test> *obj = (Container<Test> *) zend_object_store_get_object(getThis() TSRMLS_CC);
obj->cpp = test;
}
function_entry test_methods[] = {
PHP_ME(Test, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
{NULL, NULL, NULL}
};
PHP_MINIT_FUNCTION(test)
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Test", test_methods);
test_ce = zend_register_internal_class(&ce TSRMLS_CC);
test_ce->create_object = test_create_handler;
memcpy(
&test_object_handlers,
zend_get_std_object_handlers(),
sizeof(zend_object_handlers)
);
test_object_handlers.clone_obj = NULL;
return SUCCESS;
}
zend_module_entry test_module_entry = {
STANDARD_MODULE_HEADER,
PHP_TEST_EXTNAME,
NULL, /* Functions */
PHP_MINIT(test), /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
PHP_TEST_EXTVER,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_TEST
extern "C" {
ZEND_GET_MODULE(test)
}
#endif
internals.h:
#ifndef INTERNALS_H_
#define INTERNALS_H_
#include "zend.h"
template <class T>
class Container
{
private:
zend_object zend;
public:
T* cpp;
Container ( zend_class_entry* classInfo );
};
#endif /* INTERNALS_H_ */
internals.cpp
#include "internals.h"
#include "zend.h"
template <class T>
Container<T>::Container ( zend_class_entry* classInfo )
: zend()
{
zend.ce = classInfo;
}
Ben aşağıdaki komutları kullanarak inşa ediyorum:
$ phpize
$ ./configure --enable-test
$ make && make install
$ php -dextension=test.so -r "var_dump( new Test );"
Sunabileceğiniz herhangi bir yardım için teşekkür ederiz