# [Help] Reason on when to declare and protect ZEND_API function

- Thread: https://externals.io/message/116900
- Original archive: https://news-web.php.net/php.internals/116900
- Started by tao.su@intel.com on 2022-01-20T08:56:10+00:00
- Messages: 3
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #116900 — tao.su@intel.com — 2022-01-20T08:56:10+00:00

URL: https://externals.io/message/116900#116900

Hello internals,

I am trying to read Zend header files to understand its functional interfaces,
but have got confusion and anybody knows why zend_startup_system_id() and zend_finalize_system_id()
do not have to be protected by BEGIN_EXTERN_C()/END_EXTERN_C() enclosure,
but zend_add_system_entropy() has to.

Is the following code intentional for any reason?
And also, these two functions do not have ZEND_API attribute. Thanks.

Zend/zend_system_id.h
BEGIN_EXTERN_C()
/* True global; Write-only during MINIT/startup */
extern ZEND_API char zend_system_id[32];

ZEND_API ZEND_RESULT_CODE zend_add_system_entropy(const char *module_name, const char *hook_name, const void *data, size_t size);
END_EXTERN_C()

void zend_startup_system_id(void);
void zend_finalize_system_id(void);


=======================================
Tony Su (Su, Tao)
make a 'lazy' programmer diligently with efficiency

---

## #116902 — Levi Morrison via internals — 2022-01-20T14:53:58+00:00

URL: https://externals.io/message/116900#116902 · In reply to: #116900

>
> Hello internals,
>
> I am trying to read Zend header files to understand its functional interfaces,
> but have got confusion and anybody knows why zend_startup_system_id() and zend_finalize_system_id()
> do not have to be protected by BEGIN_EXTERN_C()/END_EXTERN_C() enclosure,
> but zend_add_system_entropy() has to.
>
> Is the following code intentional for any reason?
> And also, these two functions do not have ZEND_API attribute. Thanks.
>
> Zend/zend_system_id.h
> BEGIN_EXTERN_C()
> /* True global; Write-only during MINIT/startup */
> extern ZEND_API char zend_system_id[32];
>
> ZEND_API ZEND_RESULT_CODE zend_add_system_entropy(const char *module_name, const char *hook_name, const void *data, size_t size);
> END_EXTERN_C()
>
> void zend_startup_system_id(void);
> void zend_finalize_system_id(void);
>
>
> =======================================
> Tony Su (Su, Tao)
> make a 'lazy' programmer diligently with efficiency
>

I haven't looked at the details of these specific functions recently,
but in general functions which are marked ZEND_API are capable of
being called from extensions and modules. These same ZEND_API
functions need to be in `extern "C"` sections for that to happen if
the extension or module is using C++.

I would guess that `zend_startup_system_id` and
`zend_finalize_system_id` do not need to be used outside of the engine
but needed to have a forward declaration for code organization
reasons.

---

## #116903 — tao.su@intel.com — 2022-01-21T01:54:11+00:00

URL: https://externals.io/message/116900#116903 · In reply to: #116902

> 
> > […]
> and zend_finalize_system_id()
> > […]
> enclosure,
> > […]
> *module_name, const char *hook_name, const void *data, size_t size);
> > […]
> 
> I haven't looked at the details of these specific functions recently,
> but in general functions which are marked ZEND_API are capable of
> being called from extensions and modules. These same ZEND_API
> functions need to be in `extern "C"` sections for that to happen if
> the extension or module is using C++.
> 
> I would guess that `zend_startup_system_id` and
> `zend_finalize_system_id` do not need to be used outside of the engine
> but needed to have a forward declaration for code organization
> reasons.

Thanks Levi for the clarification. Things become clearer. Here are some following questions
1) when you say 'outside of the engine', what is the boundary of outside/inside?
     My understanding is that all code under Zend/ folder is considered as inside the Zend engine;
     Other components outside that folder should be considered as consumer/user of Zend. 
     Is this correct? Pls fix me if I mistook something.

     Functions marked with ZEND_API in header files under Zend/ folder 
     should be thought as the interface for outside users. Technically, 
     these functions should be marked with `extern "C"`  to support 
     C++ extension/module. 
     Is this correct? Pls fix me if I mistook something.

2) a quick search shows that main/main.c calls zend_startup_system_id()
     If main/main.c is a Zend user, logically, zend_startup_system_id() 
     should be declared with ZEND_API and extern "C"? 
   
     /* extract from main/main.c::php_module_startup() */
    /* Begin to fingerprint the process state */
    zend_startup_system_id(); 

3) I found another Zend/zend_gdb.h header file where three functions 
     are marked with ZEND_API but are not enclosed by `extern "C"`.
     /* Zend/zend_gdb.h */
     ZEND_API bool zend_gdb_register_code(const void *object, size_t size);
     ZEND_API void zend_gdb_unregister_all(void);
     ZEND_API bool zend_gdb_present(void);
     
4)  In Zend/zend.gdb.c source file, I saw a function __jit_debug_register_code() 
      marked with ZEND_API, but not declared in header file? 
      Logically and programmatically, I got confused and could not grasp ZEND_API usage style.

      /* Zend/zend_gdb.c */
      ZEND_API zend_never_inline void __jit_debug_register_code(void)
      {
	__asm__ __volatile__("");
      }

-- Tao Su
