Search code examples
phpc++php-extension

Error 'zif_test_addme': undeclared identifier - php extension development


i am new to php extension development in windows and following this article series to learn it:- https://jojokahanding.wordpress.com/2014/05/26/writing-php-extensions-for-windowswriting-the-extension/

I've successfully built compile environment for extension development by following this article . It was building successfully. But when i wrote function in it to add two numeric values and tried to build it. It throws me this error at Line 11 in phpTestModule.php:-

'zif_test_addme': undeclared identifier 

Line 11 code is :-

  PHP_FE(test_addme,NULL)

Why am i getting this error?

I have googled and found this from php website and tried to replace PHP_FE by ZEND_FE and end it by ZEND_FE_END. But even that also didn't work and i end up getting same error. Plz help.

PS :- I am using Visual Studio 2017 and PHP 7.0.22 to build extension and my system is 64 bit.

Code snippets:-

phpTestModule.cpp

// phpTestModule.cpp : Defines the exported functions for the DLL 
application.
//

#include "stdafx.h"


#define PHP_TEST_EXTNAME "test"
#define PHP_TEST_VERSION "1.0.30"

zend_function_entry test_functions[] = {
    PHP_FE(test_addme,NULL)
    {NULL,NULL,NULL}
};

zend_module_entry test_module_entry = {
#if  ZEND_MODULE_API_NO>=20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_TEST_EXTNAME,
    test_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
#if ZEND_MODULE_API_NO>=20010901
    PHP_TEST_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(test);

PHP_FUNCTION(test_addme)
{
    long paramOne;
    long paramTwo;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &paramOne, &paramTwo) == FAILURE)
    {
        RETURN_FALSE;
    }
    RETURN_LONG(paramOne + paramTwo);
}

stdafx.h

    // stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

#ifdef _DEBUG
#define ZEND_DEBUG 1
#else
#define ZEND_DEBUG 0
#endif

#define ZTS 1
#define ZEND_WIN32 1
#define PHP_WIN32 1

#include<math.h>
#include<wchar.h>
#include<io.h>
#include<php.h>

#pragma comment(lib,"php7ts.lib")
// TODO: reference additional headers your program requires here

Solution

  • You need to forward-declare the PHP function binding. You can do this either in the header as an external function or as a static function in the phpTestModule.cpp compilation unit.

    Make sure to use the PHP_FUNCTION macro to do this just like you did for the definition.

    Example

    // Forward declare PHP function bindings:
    static PHP_FUNCTION(test_addme);
    
    // Define list of functions provided by the extension module:
    zend_function_entry test_functions[] = {
        PHP_FE(test_addme,NULL)
        {NULL,NULL,NULL}
    };
    
    // PHP function binding definition:
    PHP_FUNCTION(test_addme)
    {
        long paramOne;
        long paramTwo;
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &paramOne, &paramTwo) == FAILURE)
        {
            RETURN_FALSE;
        }
        RETURN_LONG(paramOne + paramTwo);
    }
    

    Explanation

    The PHP_FUNCTION macro basically evaluates to a normal C function declaration/definition. It maps to something like void zif_test_addme(INTERNAL_FUNCTION_PARAMETERS) where INTERNAL_FUNCTION_PARAMETERS is a macro defining the actual arguments required by the function binding implementation (you don't actually have to worry about these). You can use this in both a declaration context or definition. Of course, a definition is also a declaration so you could have just moved the implementation of PHP_FUNCTION(test_addme) before the zend_function_entry declaration.