phpccmakemakefilephp-extension

C Module for PHP expected expression during PHP_FE


I'm trying to write a Hello World repository that takes a standard C function and exposes it as an internal/built-in function to PHP (and other languages written in C).

[ 27%] Building C object CMakeFiles/carbon_php.dir/bindings/php/carbon_php.c.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -Dcarbon_php_EXPORTS -I/Users/richardmiles/CLionProjects/OmniLang-C-Template/../php-src/main -I/Users/richardmiles/CLionProjects/OmniLang-C-Template/../php-src/Zend -I/Users/richardmiles/CLionProjects/OmniLang-C-Template/../php-src/TSRM -I/Users/richardmiles/CLionProjects/OmniLang-C-Template/../php-src -I/usr/local/Frameworks/Python.framework/Versions/3.12/include/python3.12 -I/Users/richardmiles/CLionProjects/OmniLang-C-Template/include -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -fPIC -MD -MT CMakeFiles/carbon_php.dir/bindings/php/carbon_php.c.o -MF CMakeFiles/carbon_php.dir/bindings/php/carbon_php.c.o.d -o CMakeFiles/carbon_php.dir/bindings/php/carbon_php.c.o -c /Users/richardmiles/CLionProjects/OmniLang-C-Template/bindings/php/carbon_php.c
/Users/richardmiles/CLionProjects/OmniLang-C-Template/bindings/php/carbon_php.c:14:55: error: expected expression
        PHP_FE(carbon_version, arginfo_carbon_version),
                                                      ^
/Users/richardmiles/CLionProjects/OmniLang-C-Template/bindings/php/carbon_php.c:15:63: error: expected expression
        PHP_FE(carbon_hello_world, arginfo_carbon_hello_world),
                                                              ^

Looking at this post suggests my usage of PHP_FE is incorrect, but I've replaced the explicit arg definitions with NULL and still no cigar. I know that these generally should work based on how I have added PHP functions to PHP-SRC in the past, but with this being a separate repository, I'm lost. Chat GPT is going in circles. I'm using Clion, so I generally think nothing syntax is causing the issue.

I've created the repo under RichardTMiles/OmniLang-C-Template open source to see the full code; here's a sample.

/src/carbon.c

const char* carbon_version() {
    return "CarbonC 1.0.0";
}

const char* helloWorld() {
    return  "Hello World!";
}

/bindings/php/carbon_php.c

#ifndef CARBON_PHP_H
#define CARBON_PHP_H

#include <php.h>
#include "carbon.h"

PHP_FUNCTION(carbon_version);
PHP_FUNCTION(carbon_hello_world);

extern zend_module_entry carbon_module_entry;
#define phpext_carbon_ptr &carbon_module_entry

ZEND_BEGIN_ARG_INFO(arginfo_carbon_version, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_carbon_hello_world, 0)
ZEND_END_ARG_INFO()

#endif // CARBON_PHP_H
#include "carbon_php.h"

PHP_FUNCTION(carbon_version) {
        const char* version = carbon_version();
        RETURN_STRING(version);
}

PHP_FUNCTION(carbon_hello_world) {
        const char* message = helloWorld();
        RETURN_STRING(message);
}

const zend_function_entry carbon_functions[] = {
        PHP_FE(carbon_version, arginfo_carbon_version),
        PHP_FE(carbon_hello_world, arginfo_carbon_hello_world),
        PHP_FE_END
};

zend_module_entry carbon_module_entry = {
        STANDARD_MODULE_HEADER,
        "carbon",                   // Extension name
        carbon_functions,           // Functions
        NULL,                       // MINIT
        NULL,                       // MSHUTDOWN
        NULL,                       // RINIT
        NULL,                       // RSHUTDOWN
        NULL,                       // MINFO
        "1.0.0",                    // Version
        STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_CARBON
ZEND_GET_MODULE(carbon)
#endif

And finally my CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(OmniLangC VERSION 1.0)

# Core C library
add_library(carbon SHARED src/carbon.c)
target_include_directories(carbon PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

# Set the path to your PHP source directory
set(PHP_SRC_DIR "../php-src")

# Allow user to specify PHP_SRC_DIR via environment variable or CMake command line
if (DEFINED ENV{PHP_SRC_DIR})
    set(PHP_SRC_DIR $ENV{PHP_SRC_DIR})
endif()

# Add PHP include directories
include_directories(
        ${PHP_SRC_DIR}/main
        ${PHP_SRC_DIR}/Zend
        ${PHP_SRC_DIR}/TSRM
)

# Check if PHP headers are found
if (NOT EXISTS "${PHP_SRC_DIR}/main/php.h" OR NOT EXISTS "${PHP_SRC_DIR}/Zend/zend.h" OR NOT EXISTS "${PHP_SRC_DIR}/TSRM/TSRM.h")
    message(FATAL_ERROR "Could not find PHP headers. Please ensure PHP_SRC_DIR is set correctly.")
else()
    message(STATUS "Found PHP headers in ${PHP_SRC_DIR}")
endif()

# PHP binding
add_library(carbon_php SHARED bindings/php/carbon_php.c)
target_include_directories(carbon_php PUBLIC ${PHP_SRC_DIR}/main ${PHP_SRC_DIR}/Zend ${PHP_SRC_DIR}/TSRM ${PHP_SRC_DIR})
target_link_libraries(carbon_php carbon)

# Python binding
find_package(PythonInterp REQUIRED)
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})

set(CYTHON_PYX_FILE ${CMAKE_CURRENT_SOURCE_DIR}/bindings/python/carbon.pyx)
set(CYTHON_C_FILE ${CMAKE_CURRENT_SOURCE_DIR}/bindings/python/carbon.c)

add_custom_command(
        OUTPUT ${CYTHON_C_FILE}
        COMMAND cython --cplus -3 ${CYTHON_PYX_FILE} -o ${CYTHON_C_FILE}
        DEPENDS ${CYTHON_PYX_FILE}
        COMMENT "Generating C source from ${CYTHON_PYX_FILE}"
)

add_library(carbon_python MODULE ${CYTHON_C_FILE})
target_link_libraries(carbon_python ${PYTHON_LIBRARIES} carbon)
target_include_directories(carbon_python PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/bindings/python)

# Ruby binding
add_library(carbon_ruby SHARED bindings/ruby/carbon_ruby.c)
target_include_directories(carbon_ruby PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/bindings/ruby)
target_link_libraries(carbon_ruby carbon)

# Node.js binding
add_library(carbon_node SHARED bindings/node/carbon_node.cpp)
target_include_directories(carbon_node PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/bindings/node)
target_link_libraries(carbon_node carbon)

I've created a README.md in the repo. If you're trying to run it locally, please take a look at that as the setup instructions.

Thanks in advance to anyone willing to help!


Solution

  • The issue is a syntax error because of a comma after the macro. Also, see the documentation for more examples.

    Change this section of code:

    const zend_function_entry carbon_functions[] = {
            PHP_FE(carbon_version, arginfo_carbon_version),
            PHP_FE(carbon_hello_world, arginfo_carbon_hello_world),
            PHP_FE_END
    };
    

    To:

    const zend_function_entry carbon_functions[] = {
            PHP_FE(carbon_version, arginfo_carbon_version)
            PHP_FE(carbon_hello_world, arginfo_carbon_hello_world)
            PHP_FE_END
    };