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

PHP-CPP method not invoked at all when being passed wrong arguments #397

Open
vedadkajtaz opened this issue Oct 18, 2018 · 4 comments
Open

Comments

@vedadkajtaz
Copy link

Hello,

I have a problem where a method (specifically, __construct) is not being called at all when provided with wrong number of arguments, resulting in unconstructed PHP object.

PHP version:

PHP 7.2.11 (cli) (built: Oct 16 2018 12:46:22) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.11, Copyright (c) 1999-2018, by Zend Technologies

PHP-CPP version; current master

bugreport.cpp

#include <iostream>
#include "PHP-CPP/phpcpp.h"

class	testClass : public Php::Base
{
	
	public:

		testClass()
		{
			Php::out << "testClass::testClass() (CPP constructor)" << std::endl;
		}

		testClass(const testClass&)
		{
			Php::out << "testClass::testClass(const testClass&) (CPP/PHP copy constructor)" << std::endl;
		}

		virtual ~testClass() noexcept override
		{
			Php::out << "testClass::~testClass() (CPP destructor)" << std::endl;
		}

		void	__construct(Php::Parameters& params)
		{
			Php::out << "testClass::__construct() (PHP constructor)" << std::endl;

			//for(const auto& param : params)
			//	Php::out << "\tparam: " << param << std::endl;
		}
		void	__destruct() noexcept
		{
			Php::out << "testClass::__destruct() (PHP destructor)" << std::endl;
		}

		void	method(Php::Parameters& params)
		{
			Php::out << "testClass::method()" << std::endl;
		}
};

extern "C" {

	PHPCPP_EXPORT void *get_module()
	{
		static Php::Extension extension("bugreport", "0.1");

		/********************************************************************/
		/* testClass */

		Php::Class<testClass>	testClass("testClass");

		testClass.method<&testClass::__construct>(
			"__construct",
			Php::Public,
			{
				Php::ByVal("first", Php::Type::String, true),
				Php::ByVal("second", Php::Type::String, true),
			}
		);

		testClass.method<&testClass::method>(
			"method",
			Php::Public
		);

		extension.add(std::move(testClass));

		return extension;
	}
}

bugreport.php

#!/usr/bin/env php
<?php
declare(strict_types=1);

dl('bugreport.so');

$a = new testClass('hello', 'world');
$a->method();

unset($a);
echo '----------------------------------------', PHP_EOL;

// Here, the invocation of testClass::__construct() is being skipped, resulting in unconstructed PHP object.
$a = new testClass('hello');
// Yet, method() is invoked
$a->method();

Expected output:

testClass::testClass() (CPP constructor)
testClass::__construct() (PHP constructor)
testClass::method()
testClass::__destruct() (PHP destructor)
testClass::~testClass() (CPP destructor)
----------------------------------------
testClass::testClass() (CPP constructor)
testClass::__construct() (PHP constructor)
testClass::method()
testClass::__destruct() (PHP destructor)
testClass::~testClass() (CPP destructor)

Actual output:

testClass::testClass() (CPP constructor)
testClass::__construct() (PHP constructor)
testClass::method()
testClass::__destruct() (PHP destructor)
testClass::~testClass() (CPP destructor)
----------------------------------------
testClass::testClass() (CPP constructor)
testClass::method()
testClass::__destruct() (PHP destructor)
testClass::~testClass() (CPP destructor)

Kind regards,

@vedadkajtaz
Copy link
Author

Note that PHP promptly warns:

PHP Warning: __construct() expects at least 2 parameter(s), 1 given in .../bugreport.php on line 14

@vedadkajtaz
Copy link
Author

Actually, the expected output would be the native PHP behavior, which is to throw ArgumentCountError, as follows.

bugreport_php.php

#!/usr/bin/env php
<?php
declare(strict_types=1);

class	testClass
{
	public function	__construct(string $first, string $second)
	{
		echo __METHOD__, PHP_EOL;
	}

	public function	method()
	{
		echo __METHOD__, PHP_EOL;
	}
}

$a = new testClass('hello', 'world');
$a->method();

unset($a);
echo '----------------------------------------', PHP_EOL;

$a = new testClass('hello');
$a->method();

Output:

testClass::__construct
testClass::method
----------------------------------------

Log:
PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function testClass::__construct(), 1 passed in .../bugreport_php.php on line 24 and exactly 2 expected in .../bugreport_php.php:7

@alain91
Copy link

alain91 commented Dec 8, 2018

I would like to investigate this issue to dive into php-cpp source code.

@alain91
Copy link

alain91 commented Dec 8, 2018

I compiled libphpcpp today from clone master.
Instead of using dl I have copied extension bugreport.so into extension-dir and added extension=bugreport into php.ini

My bugreport2.php is

#!/usr/bin/env php
<?php
declare(strict_types=1);

$result = @extension_loaded('bugreport');

if (false === $result) die("error extension loaded bugreport.so\n");

$a = new testClass('hello', 'world');
$a->method();

unset($a);
echo '----------------------------------------', PHP_EOL;

// Here, the invocation of testClass::__construct() is being skipped, resulting in unconstructed PHP object.
$a = new testClass('hello');
// Yet, method() is invoked
$a->method();

and the log is

testClass::testClass() (CPP constructor)
testClass::__construct() (PHP constructor)
testClass::method()
testClass::__destruct() (PHP destructor)
testClass::~testClass() (CPP destructor)
----------------------------------------
testClass::testClass() (CPP constructor)
PHP Warning:  __construct() expects at least 2 parameter(s), 1 given in bugreport/bugreport2.php on line 16
testClass::method()
testClass::__destruct() (PHP destructor)
testClass::~testClass() (CPP destructor)

It seems that it works fine for me. No invocation is skipped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants