Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

embed development problem:Segmentation fault #17502

Closed
KingBes opened this issue Jan 18, 2025 · 1 comment
Closed

embed development problem:Segmentation fault #17502

KingBes opened this issue Jan 18, 2025 · 1 comment

Comments

@KingBes
Copy link

KingBes commented Jan 18, 2025

Description

class.h

#include <sapi/embed/php_embed.h>

static zend_object_handlers class_object_handlers;

typedef struct my_php_class_t
{
    zend_object std;
} my_php_class_t;

PHP_METHOD(MyPhpClass, __construct)
{
    RETURN_NULL();
}

ZEND_BEGIN_ARG_INFO_EX(arginfo__construct, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
ZEND_END_ARG_INFO()

PHP_METHOD(MyPhpClass, myMethod)
{
    long num; 

    ZEND_PARSE_PARAMETERS_START(1, 1)
    Z_PARAM_LONG(num)
    ZEND_PARSE_PARAMETERS_END();

    RETURN_LONG(num * 2);
}

ZEND_BEGIN_ARG_INFO_EX(arginfo_myMethod, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
ZEND_ARG_TYPE_INFO(0, num, IS_LONG, 0)
ZEND_END_ARG_INFO()

static const zend_function_entry my_php_class[] = {
    PHP_ME(MyPhpClass, __construct, arginfo__construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
        PHP_ME(MyPhpClass, myMethod, arginfo_myMethod, ZEND_ACC_PUBLIC)
            PHP_FE_END};

zend_object *class_new(zend_class_entry *ce)
{
    my_php_class_t *class = zend_object_alloc(sizeof(my_php_class_t), ce);

    zend_object_std_init(&class->std, ce);
    class->std.handlers = &class_object_handlers;
    return &class->std;
}

void register_class()
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "MyPhpClass", my_php_class);
    ce.create_object = class_new;
    // ce.default_object_handlers = &class_object_handlers;
    memcpy(&class_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
    class_object_handlers.offset = XtOffsetOf(my_php_class_t, std);
    zend_register_internal_class(&ce);
    printf("register_class ok\n");
}

main.c

#include "class.h"

int main(int argc, char **argv)
{
    PHP_EMBED_START_BLOCK(argc, argv)

    register_class();

    zend_file_handle file_handle;
    zend_stream_init_filename(&file_handle, "index.php");
    if (php_execute_script(&file_handle) == FAILURE)
    {
        php_printf("Failed to execute PHP script.\n");
    }
    PHP_EMBED_END_BLOCK()
    return 0;
}

index.php

<?php

$MyPhpClass = new MyPhpClass();

var_dump($MyPhpClass->myMethod(123));

result

Segmentation fault

PHP Version

8.3.15

Operating System

Linux version 5.15.146.1-microsoft-standard-WSL2

@nielsdos
Copy link
Member

nielsdos commented Jan 18, 2025

This happens because EG(current_module) is NULL at the point in time you're registering your class.
You're not respecting the PHP lifecycle and module system. If you want to add your own functions and classes you need to do this via a module and you'll have to create a zend_module_entry etc. Then in the MINIT hook you can register your class.
See https://www.phpinternalsbook.com/php7/extensions_design/php_lifecycle.html and https://www.phpinternalsbook.com/php7/extensions_design/extension_skeleton.html

Also a tip: you can use a .stub.php file instead of manually writing the arginfo. The arginfo can then be generated using ./build/gen_stub.php.

@nielsdos nielsdos closed this as not planned Won't fix, can't repro, duplicate, stale Jan 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants