Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:19559 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 29761 invoked by uid 1010); 10 Oct 2005 18:46:28 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 29746 invoked from network); 10 Oct 2005 18:46:28 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 10 Oct 2005 18:46:28 -0000 X-Host-Fingerprint: 81.169.182.136 ajaxatwork.net Linux 2.4/2.6 Received: from ([81.169.182.136:46897] helo=strato.aixcept.de) by pb1.pair.com (ecelerity 2.0 beta r(6323M)) with SMTP id 6F/F5-54476-307BA434 for ; Mon, 10 Oct 2005 14:46:27 -0400 Received: from [192.168.1.3] (dslb-084-063-017-077.pools.arcor-ip.net [84.63.17.77]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by strato.aixcept.de (Postfix) with ESMTP id 9DD00610285; Mon, 10 Oct 2005 20:47:53 +0200 (CEST) Date: Mon, 10 Oct 2005 20:44:22 +0200 Reply-To: Marcus Boerger X-Priority: 3 (Normal) Message-ID: <1174385027.20051010204422@marcus-boerger.de> To: David Olsson Cc: internals@lists.php.net In-Reply-To: <8F.35.54476.F96D4434@pb1.pair.com> References: <4A.46.54476.C2272434@pb1.pair.com> <002801c5c8fe$b62d2ef0$6d561a44@lighthammer> <8F.35.54476.F96D4434@pb1.pair.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Re: zval "passthrough"? From: helly@php.net (Marcus Boerger) Hello David, Thursday, October 6, 2005, 9:49:35 AM, you wrote: > Thanks! That was very useful information. Had to go with the #3a > solution as I need to be compatible with PHP4. > I still have some problems with my extension though. The extension > maintains a module global C++ std::map allocated in my MINIT function > and deallocated in my MSHUTDOWN function. This map stores some zval * > added to the map like this: > int nameLen; > char *name; > zval *v; > zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz!", &v); > zval *newv = new zval[1]; > *newv = *v; > zval_copy_ctor(newv); > (*reinterpret_cast *>(PSV_G(psvs)))[name] = newv; do you have any idea what a reinterpret_cast<>() does? So probably change your code so that you are actually use what you think you do. apart from that you should consider storing the zval's rather than pointers. > where PSV_G(psvs) is a pointer to the map. The problem is that the > content of the map may change or dissapear without my extension > accessing it at all. Does the Zend engine do anything with the memory I > have allocated? Currently i allocate memory for the map with new instead > of emalloc but should that make any difference (except for larger risks > for memory leaks)? > Thanks in advance! > David Olsson > Sara Golemon wrote: >>> I'm writing a PHP extension in C++ which need to provide a function >>> which will take as a parameter a zval *. This zval * should, when the >>> function has completed its task, simply be returned unmodified. How do >>> I accomplish this? I've tried something like this: >>> >>> return_value = v; >>> >> There are two problems here: >> >> #1 return_value is just a parameter in the prototype: >> >> void zif_my_func(int ht, zval *return_value, zval **return_value_ptr, >> zval *this_ptr, int return_value_used TSRMLS_DC) >> >> So when you set: return_value = v; You are in fact changing where >> return_value points, but you're not doing anything to the contents of >> the return_value zval that the calling scope (the engine) knows about. >> You're just changing the local pointer to look at another address. >> >> Using return_value_ptr you can both clean up the original memory >> allocated for return_value, and change what the engine knows about >> return_value since you have the pointer to the pointer which the engine >> uses: >> >> /* Destroy old return_value (prevents leaks) */ >> zval_ptr_dtor(return_value_ptr); >> >> /* Point return_value at the passed in val */ >> *return_value_ptr = v; >> >> This brings us to the second problem: >> >> #2 The refcount of v will have been temporarily increased by the engine >> when it was placed on the parameter stack, however when the function >> exits, that refcount will be decremented back down and there will be no >> refcount associated with the copy stored in return_value. Long story >> short you need to add ref the value when you assign it to a new container: >> >> ZVAL_ADDREF(v); >> zval_ptr_dtor(return_value_ptr); >> *return_value_ptr = v; >> >> >> Now for problem number 3 (What, you thought I'd stop at two?) >> >> If v was an is_ref value, with a refcount of only 2 at the time of >> leaving your internal function, and you're using PHP 5.0, the function >> return will break the reference set. This is a known bug and is fixed >> in the 5.1 branch. >> >> And problem #3a (PHP4 compatability) >> >> PHP4 doesn't even have the return_value_ptr parameter so you can't even >> do that stuff with it. What you can do is perform a deep copy on the >> value: >> >> *return_value = *v; >> zval_copy_ctor(return_value); >> >> While it's less memory/cpu efficient, it is usable across all versions. >> >> -Sara Best regards, Marcus