Commit c0250bac3ac for php

commit c0250bac3ac1983a099a20b5f6c6ef5787dcbc3d
Author: Gina Peter Banyard <girgias@php.net>
Date:   Fri Oct 23 21:51:52 2026 +0100

    intl: stop including headers as C extern (#24617)

    Except for arginfo header as PHP_FUNCTION/PHP_METHOD are marked as U_CFUNC and the `ext/date/php_date.h` header doesn't use extern C.

    We now specificy the header symbols that _need_ to follow the C function ABI, meaning in some places we drop U_CFUNC declarations and in others we add it.

    Also use the `BEGIN_EXTERN_C()` portability macro when possible so that searching for this is easier.

diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp
index 35c5b6956b4..c9f2a53b58d 100644
--- a/ext/intl/breakiterator/breakiterator_class.cpp
+++ b/ext/intl/breakiterator/breakiterator_class.cpp
@@ -24,14 +24,14 @@

 #include <typeinfo>

-extern "C" {
 #define USE_BREAKITERATOR_POINTER 1
 #include "breakiterator_class.h"
+BEGIN_EXTERN_C()
 #include "breakiterator_arginfo.h"
+END_EXTERN_C()
 #include <zend_exceptions.h>
 #include <zend_interfaces.h>
 #include <assert.h>
-}

 using PHP::CodePointBreakIterator;
 using icu::RuleBasedBreakIterator;
diff --git a/ext/intl/breakiterator/breakiterator_class.h b/ext/intl/breakiterator/breakiterator_class.h
index f4258cbae5b..9038aa3e7f7 100644
--- a/ext/intl/breakiterator/breakiterator_class.h
+++ b/ext/intl/breakiterator/breakiterator_class.h
@@ -62,6 +62,7 @@ typedef struct {
 		RETURN_THROWS(); \
 	}

+BEGIN_EXTERN_C()
 void breakiterator_object_create(zval *object, BreakIterator *break_iter, int brand_new);

 void breakiterator_register_BreakIterator_class(void);
@@ -70,5 +71,6 @@ extern zend_class_entry *BreakIterator_ce_ptr,
 						*RuleBasedBreakIterator_ce_ptr;

 extern zend_object_handlers BreakIterator_handlers;
+END_EXTERN_C()

 #endif /* #ifndef BREAKITERATOR_CLASS_H */
diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp
index def0fa9d9fc..8b1c136a064 100644
--- a/ext/intl/breakiterator/breakiterator_iterators.cpp
+++ b/ext/intl/breakiterator/breakiterator_iterators.cpp
@@ -21,15 +21,15 @@
 #include "breakiterator_iterators.h"
 #include "../common/common_enum.h"

-extern "C" {
 #define USE_BREAKITERATOR_POINTER
 #include "breakiterator_class.h"
+BEGIN_EXTERN_C()
 #include "breakiterator_iterators_arginfo.h"
+END_EXTERN_C()
 #include "../intl_convert.h"
 #include "../locale/locale.h"
 #include <zend_exceptions.h>
 #include <zend_interfaces.h>
-}

 static zend_class_entry *IntlPartsIterator_ce_ptr;

diff --git a/ext/intl/breakiterator/breakiterator_iterators.h b/ext/intl/breakiterator/breakiterator_iterators.h
index 3ac07cd271c..bca19cc2b0b 100644
--- a/ext/intl/breakiterator/breakiterator_iterators.h
+++ b/ext/intl/breakiterator/breakiterator_iterators.h
@@ -16,10 +16,8 @@

 #include <unicode/umachine.h>

-U_CDECL_BEGIN
 #include <math.h>
 #include <php.h>
-U_CDECL_END

 typedef enum {
 	PARTS_ITERATOR_KEY_SEQUENTIAL,
diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp b/ext/intl/breakiterator/breakiterator_methods.cpp
index 60659915bf8..05d8c659bf2 100644
--- a/ext/intl/breakiterator/breakiterator_methods.cpp
+++ b/ext/intl/breakiterator/breakiterator_methods.cpp
@@ -21,14 +21,12 @@

 #include "breakiterator_iterators.h"

-extern "C" {
 #include "../php_intl.h"
 #define USE_BREAKITERATOR_POINTER 1
 #include "breakiterator_class.h"
 #include "../locale/locale.h"
 #include <zend_exceptions.h>
 #include <zend_interfaces.h>
-}

 using PHP::CodePointBreakIterator;
 using icu::BreakIterator;
diff --git a/ext/intl/breakiterator/codepointiterator_methods.cpp b/ext/intl/breakiterator/codepointiterator_methods.cpp
index 3b5044cb45a..934e10c2cbf 100644
--- a/ext/intl/breakiterator/codepointiterator_methods.cpp
+++ b/ext/intl/breakiterator/codepointiterator_methods.cpp
@@ -14,10 +14,8 @@

 #include "codepointiterator_internal.h"

-extern "C" {
 #define USE_BREAKITERATOR_POINTER 1
 #include "breakiterator_class.h"
-}

 using PHP::CodePointBreakIterator;

diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
index 611144b58ab..5a978a97f43 100644
--- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
+++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
@@ -15,12 +15,10 @@
 #include <unicode/rbbi.h>
 #include <memory>

-extern "C" {
 #define USE_BREAKITERATOR_POINTER 1
 #include "breakiterator_class.h"
 #include <zend_exceptions.h>
 #include <limits.h>
-}

 #include "../intl_convertcpp.h"
 #include "../intl_common.h"
diff --git a/ext/intl/calendar/calendar_class.cpp b/ext/intl/calendar/calendar_class.cpp
index 46e8ba49b89..b95028e0c9d 100644
--- a/ext/intl/calendar/calendar_class.cpp
+++ b/ext/intl/calendar/calendar_class.cpp
@@ -21,15 +21,15 @@
 #include <unicode/calendar.h>
 #include <unicode/gregocal.h>

-extern "C" {
 #define USE_TIMEZONE_POINTER 1
 #include "../timezone/timezone_class.h"
 #define USE_CALENDAR_POINTER 1
 #include "calendar_class.h"
+BEGIN_EXTERN_C()
 #include "calendar_arginfo.h"
+END_EXTERN_C()
 #include <zend_exceptions.h>
 #include <assert.h>
-}

 using icu::GregorianCalendar;
 using icu::Locale;
@@ -40,7 +40,7 @@ zend_class_entry *GregorianCalendar_ce_ptr;
 zend_object_handlers Calendar_handlers;
 /* }}} */

-U_CFUNC	void calendar_object_create(zval *object,
+void calendar_object_create(zval *object,
 									Calendar *calendar)
 {
 	UClassID classId = calendar->getDynamicClassID();
@@ -57,14 +57,14 @@ U_CFUNC	void calendar_object_create(zval *object,
 	calendar_object_construct(object, calendar);
 }

-U_CFUNC Calendar *calendar_fetch_native_calendar(zend_object *object)
+Calendar *calendar_fetch_native_calendar(zend_object *object)
 {
 	Calendar_object *co = php_intl_calendar_fetch_object(object);

 	return co->ucal;
 }

-U_CFUNC void calendar_object_construct(zval *object,
+void calendar_object_construct(zval *object,
 									   Calendar *calendar)
 {
 	Calendar_object *co;
diff --git a/ext/intl/calendar/calendar_class.h b/ext/intl/calendar/calendar_class.h
index 7c74aede947..f025bd4525a 100644
--- a/ext/intl/calendar/calendar_class.h
+++ b/ext/intl/calendar/calendar_class.h
@@ -63,10 +63,12 @@ Calendar *calendar_fetch_native_calendar(zend_object *object);

 void calendar_object_construct(zval *object, Calendar *calendar);

+BEGIN_EXTERN_C()
 void calendar_register_IntlCalendar_class(void);

 extern zend_class_entry *Calendar_ce_ptr, *GregorianCalendar_ce_ptr;

 extern zend_object_handlers Calendar_handlers;
+END_EXTERN_C()

 #endif /* #ifndef CALENDAR_CLASS_H */
diff --git a/ext/intl/calendar/calendar_methods.cpp b/ext/intl/calendar/calendar_methods.cpp
index f4c9cb36cde..990eea9eeaf 100644
--- a/ext/intl/calendar/calendar_methods.cpp
+++ b/ext/intl/calendar/calendar_methods.cpp
@@ -27,7 +27,6 @@
 #include "../intl_convertcpp.h"
 #include "../common/common_date.h"

-extern "C" {
 #include "../php_intl.h"
 #define USE_TIMEZONE_POINTER 1
 #include "../timezone/timezone_class.h"
@@ -36,8 +35,9 @@ extern "C" {
 #include "../intl_convert.h"
 #include <zend_exceptions.h>
 #include <zend_interfaces.h>
+BEGIN_EXTERN_C()
 #include <ext/date/php_date.h>
-}
+END_EXTERN_C()
 #include "../common/common_enum.h"

 using icu::Locale;
diff --git a/ext/intl/calendar/gregoriancalendar_methods.cpp b/ext/intl/calendar/gregoriancalendar_methods.cpp
index 9573bdf5d9e..bb276ddedf0 100644
--- a/ext/intl/calendar/gregoriancalendar_methods.cpp
+++ b/ext/intl/calendar/gregoriancalendar_methods.cpp
@@ -24,16 +24,16 @@
 #include <unicode/gregocal.h>
 #include <unicode/ustring.h>

-extern "C" {
 #include "../php_intl.h"
 #include "../intl_common.h"
 #define USE_TIMEZONE_POINTER 1
 #include "../timezone/timezone_class.h"
 #define USE_CALENDAR_POINTER 1
 #include "calendar_class.h"
+BEGIN_EXTERN_C()
 #include <ext/date/php_date.h>
+END_EXTERN_C()
 #include "zend_exceptions.h"
-}

 using icu::GregorianCalendar;
 using icu::Locale;
diff --git a/ext/intl/collator/collator_attr.cpp b/ext/intl/collator/collator_attr.cpp
index 04ce848abe0..e79e2e13974 100644
--- a/ext/intl/collator/collator_attr.cpp
+++ b/ext/intl/collator/collator_attr.cpp
@@ -22,9 +22,7 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
-}
 #include "collator_class.h"
 #include "collator_convert.h"

diff --git a/ext/intl/collator/collator_class.cpp b/ext/intl/collator/collator_class.cpp
index 808f7ae127d..6e4996d065f 100644
--- a/ext/intl/collator/collator_class.cpp
+++ b/ext/intl/collator/collator_class.cpp
@@ -15,11 +15,12 @@

 #include "collator.h"
 #include "collator_class.h"
-extern "C" {
 #include "php_intl.h"
 #include "intl_error.h"
+
+BEGIN_EXTERN_C()
 #include "collator_arginfo.h"
-}
+END_EXTERN_C()
 #include "collator_sort.h"
 #include "collator_convert.h"

diff --git a/ext/intl/collator/collator_class.h b/ext/intl/collator/collator_class.h
index 1f1629cce77..84790e88f80 100644
--- a/ext/intl/collator/collator_class.h
+++ b/ext/intl/collator/collator_class.h
@@ -18,15 +18,9 @@

 #include <php.h>

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "../intl_common.h"
 #include "../intl_error.h"
 #include "../intl_data.h"
-#ifdef __cplusplus
-}
-#endif

 #include <unicode/ucol.h>

@@ -64,17 +58,12 @@ static zend_always_inline zend_result collator_check_initialized(Collator_object

 	return SUCCESS;
 }
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void collator_register_Collator_symbols(int module_number);
 void collator_object_destroy( Collator_object* co );
-#ifdef __cplusplus
-}
-#endif

 extern zend_class_entry *Collator_ce_ptr;
+END_EXTERN_C()

 /* Auxiliary macros */

diff --git a/ext/intl/collator/collator_compare.cpp b/ext/intl/collator/collator_compare.cpp
index 4bfe0956a3f..5607f1fd330 100644
--- a/ext/intl/collator/collator_compare.cpp
+++ b/ext/intl/collator/collator_compare.cpp
@@ -22,10 +22,8 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
 #include "intl_convert.h"
-}
 #include "collator_class.h"

 /* {{{ Compare two strings. */
diff --git a/ext/intl/collator/collator_convert.cpp b/ext/intl/collator/collator_convert.cpp
index 0f6e62f1b55..7edfe61839e 100644
--- a/ext/intl/collator/collator_convert.cpp
+++ b/ext/intl/collator/collator_convert.cpp
@@ -22,10 +22,8 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
 #include "intl_convert.h"
-}
 #include "collator_class.h"
 #include "collator_is_numeric.h"
 #include "collator_convert.h"
@@ -127,7 +125,7 @@ static void collator_convert_hash_item_from_utf16_to_utf8(
 /* {{{ collator_convert_hash_from_utf8_to_utf16
  *  Convert values of the given hash from UTF-8 encoding to UTF-16LE.
  */
-U_CFUNC void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status )
+void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status )
 {
 	zend_ulong    hashIndex;
 	zval *hashData;
@@ -146,7 +144,7 @@ U_CFUNC void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCo
 /* {{{ collator_convert_hash_from_utf16_to_utf8
  * Convert values of the given hash from UTF-16LE encoding to UTF-8.
  */
-U_CFUNC void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status )
+void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status )
 {
 	zend_ulong hashIndex;
 	zend_string *hashKey;
@@ -171,7 +169,7 @@ U_CFUNC void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCo
  *
  * @return zval* Converted string.
  */
-U_CFUNC zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval, zval *rv )
+zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval, zval *rv )
 {
 	zend_string* u8str;
 	UErrorCode status = U_ZERO_ERROR;
@@ -190,7 +188,7 @@ U_CFUNC zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval, zval *rv )
 }
 /* }}} */

-U_CFUNC zend_string *collator_convert_zstr_utf8_to_utf16(zend_string *utf8_str)
+zend_string *collator_convert_zstr_utf8_to_utf16(zend_string *utf8_str)
 {
 	UErrorCode status = U_ZERO_ERROR;

@@ -209,7 +207,7 @@ U_CFUNC zend_string *collator_convert_zstr_utf8_to_utf16(zend_string *utf8_str)
 /* {{{ collator_convert_object_to_string
  * Convert object to UTF16-encoded string.
  */
-U_CFUNC zval* collator_convert_object_to_string( zval* obj, zval *rv )
+zval* collator_convert_object_to_string( zval* obj, zval *rv )
 {
 	zval* zstr        = nullptr;
 	UErrorCode status = U_ZERO_ERROR;
@@ -272,7 +270,7 @@ U_CFUNC zval* collator_convert_object_to_string( zval* obj, zval *rv )
  *
  * @return zval* Number. If str is not numeric string return number zero.
  */
-U_CFUNC zval* collator_convert_string_to_number( zval* str, zval *rv )
+zval* collator_convert_string_to_number( zval* str, zval *rv )
 {
 	zval* num = collator_convert_string_to_number_if_possible( str, rv );
 	if( num == str )
@@ -296,7 +294,7 @@ U_CFUNC zval* collator_convert_string_to_number( zval* str, zval *rv )
  *
  * @return zval* Number. If str is not numeric string return number zero.
  */
-U_CFUNC zval* collator_convert_string_to_double( zval* str, zval *rv )
+zval* collator_convert_string_to_double( zval* str, zval *rv )
 {
 	zval* num = collator_convert_string_to_number( str, rv );
 	if( Z_TYPE_P(num) == IS_LONG )
@@ -317,7 +315,7 @@ U_CFUNC zval* collator_convert_string_to_double( zval* str, zval *rv )
  * @return zval* Number if str is numeric string. Otherwise
  *               original str param.
  */
-U_CFUNC zval* collator_convert_string_to_number_if_possible( zval* str, zval *rv )
+zval* collator_convert_string_to_number_if_possible( zval* str, zval *rv )
 {
 	uint8_t is_numeric = 0;
 	zend_long lval      = 0;
@@ -351,7 +349,7 @@ U_CFUNC zval* collator_convert_string_to_number_if_possible( zval* str, zval *rv
  *
  * @return zend_string* UTF16 string.
  */
-U_CFUNC zend_string *collator_zval_to_string(zval *arg)
+zend_string *collator_zval_to_string(zval *arg)
 {
 	// TODO: This is extremely weird in that it leaves pre-existing strings alone and does not
 	// perform a UTF-8 to UTF-16 conversion for them. The assumption is that values that are
@@ -379,7 +377,7 @@ U_CFUNC zend_string *collator_zval_to_string(zval *arg)
  * @return zval* Normalized copy of arg or unmodified arg
  *               if normalization is not needed.
  */
-U_CFUNC zval* collator_normalize_sort_argument( zval* arg, zval *rv )
+zval* collator_normalize_sort_argument( zval* arg, zval *rv )
 {
 	zval* n_arg = nullptr;

diff --git a/ext/intl/collator/collator_convert.h b/ext/intl/collator/collator_convert.h
index 1d65d9d2d76..13ffbaabd72 100644
--- a/ext/intl/collator/collator_convert.h
+++ b/ext/intl/collator/collator_convert.h
@@ -19,9 +19,6 @@
 #include <php.h>
 #include <unicode/utypes.h>

-#ifdef __cplusplus
-extern "C" {
-#endif
 void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status );
 void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status );

@@ -35,8 +32,5 @@ zval* collator_convert_string_to_number_if_possible( zval* str, zval *rv );
 zval* collator_convert_string_to_double( zval* str, zval *rv );

 zend_string *collator_zval_to_string(zval *arg);
-#ifdef __cplusplus
-}
-#endif

 #endif // COLLATOR_CONVERT_H
diff --git a/ext/intl/collator/collator_create.cpp b/ext/intl/collator/collator_create.cpp
index d2f16b67a26..65397bfb573 100644
--- a/ext/intl/collator/collator_create.cpp
+++ b/ext/intl/collator/collator_create.cpp
@@ -22,9 +22,7 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
-}
 #include "collator_class.h"
 #include "intl_data.h"

diff --git a/ext/intl/collator/collator_error.cpp b/ext/intl/collator/collator_error.cpp
index 2a1eda8f9f3..c16140bbe22 100644
--- a/ext/intl/collator/collator_error.cpp
+++ b/ext/intl/collator/collator_error.cpp
@@ -22,9 +22,7 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
-}
 #include "collator_class.h"

 /* {{{ Get collator's last error code. */
diff --git a/ext/intl/collator/collator_locale.cpp b/ext/intl/collator/collator_locale.cpp
index 20aba988fb4..2d346f439c9 100644
--- a/ext/intl/collator/collator_locale.cpp
+++ b/ext/intl/collator/collator_locale.cpp
@@ -22,9 +22,7 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
-}
 #include "collator_class.h"
 #include "intl_convert.h"

diff --git a/ext/intl/collator/collator_sort.cpp b/ext/intl/collator/collator_sort.cpp
index dc5898d23a6..37f3be5ed29 100644
--- a/ext/intl/collator/collator_sort.cpp
+++ b/ext/intl/collator/collator_sort.cpp
@@ -22,10 +22,8 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
 #include "intl_convert.h"
-}
 #include "collator.h"
 #include "collator_class.h"
 #include "collator_sort.h"
diff --git a/ext/intl/common/common_date.cpp b/ext/intl/common/common_date.cpp
index c9eb45b0f2d..db800cc01cc 100644
--- a/ext/intl/common/common_date.cpp
+++ b/ext/intl/common/common_date.cpp
@@ -16,12 +16,13 @@

 #include <unicode/calendar.h>

-extern "C" {
 #include "../php_intl.h"
 #define USE_CALENDAR_POINTER 1
 #include "../calendar/calendar_class.h"
+
+U_CDECL_BEGIN
 #include <ext/date/php_date.h>
-}
+U_CDECL_END

 using icu::TimeZone;
 using icu::UnicodeString;
diff --git a/ext/intl/common/common_date.h b/ext/intl/common/common_date.h
index a3a58eb3b03..42936875e36 100644
--- a/ext/intl/common/common_date.h
+++ b/ext/intl/common/common_date.h
@@ -17,10 +17,8 @@

 #include <unicode/umachine.h>

-U_CDECL_BEGIN
 #include <php.h>
 #include "../intl_error.h"
-U_CDECL_END

 #ifdef __cplusplus

diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp
index 16c89207491..b9549194507 100644
--- a/ext/intl/common/common_enum.cpp
+++ b/ext/intl/common/common_enum.cpp
@@ -18,21 +18,13 @@

 #include "../intl_cppshims.h"

-// Fix build on Windows/old versions of ICU
-#include <stdio.h>
-
-extern "C" {
 #include <zend_attributes.h>
-}
+#include <zend_interfaces.h>
+#include <zend_exceptions.h>

 #include "common_enum.h"
 #include "common_arginfo.h"

-extern "C" {
-#include <zend_interfaces.h>
-#include <zend_exceptions.h>
-}
-
 zend_class_entry *IntlIterator_ce_ptr;
 zend_object_handlers IntlIterator_handlers;

diff --git a/ext/intl/common/common_enum.h b/ext/intl/common/common_enum.h
index e4a8b5461df..48a11bfbbea 100644
--- a/ext/intl/common/common_enum.h
+++ b/ext/intl/common/common_enum.h
@@ -17,17 +17,12 @@
 #define INTL_COMMON_ENUM_H

 #include <unicode/umachine.h>
-#ifdef __cplusplus
+
 #include <unicode/strenum.h>
-extern "C" {
 #include <math.h>
-#endif
 #include <php.h>
 #include "../intl_error.h"
 #include "../intl_data.h"
-#ifdef __cplusplus
-}
-#endif

 #define INTLITERATOR_ERROR(ii)						(ii)->err
 #define INTLITERATOR_ERROR_P(ii)					&(INTLITERATOR_ERROR(ii))
diff --git a/ext/intl/common/common_error.cpp b/ext/intl/common/common_error.cpp
index 8d0cca52bb7..7938cbd1dff 100644
--- a/ext/intl/common/common_error.cpp
+++ b/ext/intl/common/common_error.cpp
@@ -17,10 +17,8 @@
 #include <config.h>
 #endif

-extern "C" {
 #include "php_intl.h"
 #include "intl_error.h"
-}

 /* {{{ Get code of the last occurred error. */
 U_CFUNC PHP_FUNCTION( intl_get_error_code )
diff --git a/ext/intl/converter/converter.cpp b/ext/intl/converter/converter.cpp
index 3023da6ef2c..55c35399fe0 100644
--- a/ext/intl/converter/converter.cpp
+++ b/ext/intl/converter/converter.cpp
@@ -22,12 +22,10 @@

 #include "converter_class.h"

-extern "C" {
 #include "converter.h"
 #include "php_intl.h"
 #include "../intl_error.h"
 #include "../intl_common.h"
-}

 #define CONV_GET(pzv)  (Z_INTL_CONVERTER_P((pzv)))
 #define THROW_UFAILURE(obj, error) php_converter_throw_failure(obj, error, \
diff --git a/ext/intl/converter/converter.h b/ext/intl/converter/converter.h
index 60967d19672..af814763651 100644
--- a/ext/intl/converter/converter.h
+++ b/ext/intl/converter/converter.h
@@ -19,14 +19,10 @@
 #include <config.h>
 #endif

-#include "php.h"
+#include "zend_portability.h"

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 int php_converter_minit(INIT_FUNC_ARGS);
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()

 #endif /* PHP_INTL_CONVERTER_H */
diff --git a/ext/intl/converter/converter_class.h b/ext/intl/converter/converter_class.h
index 9b16e3b417d..3adfd3a6e52 100644
--- a/ext/intl/converter/converter_class.h
+++ b/ext/intl/converter/converter_class.h
@@ -17,14 +17,7 @@

 #include "php.h"
 #include <unicode/ucnv.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "../intl_error.h"
-#ifdef __cplusplus
-}
-#endif

 typedef struct _php_converter_object {
 	UConverter *src, *dest;
diff --git a/ext/intl/dateformat/dateformat.cpp b/ext/intl/dateformat/dateformat.cpp
index 64454a8afde..adc963e4bf2 100644
--- a/ext/intl/dateformat/dateformat.cpp
+++ b/ext/intl/dateformat/dateformat.cpp
@@ -17,9 +17,7 @@

 #include <unicode/udat.h>

-extern "C" {
 #include "php_intl.h"
-}
 #include "dateformat_class.h"
 #include "dateformat.h"

diff --git a/ext/intl/dateformat/dateformat_attr.cpp b/ext/intl/dateformat/dateformat_attr.cpp
index 170a85889d5..fc248ba5da1 100644
--- a/ext/intl/dateformat/dateformat_attr.cpp
+++ b/ext/intl/dateformat/dateformat_attr.cpp
@@ -15,10 +15,8 @@
 #include <config.h>
 #endif

-extern "C" {
 #include "../php_intl.h"
 #include "../intl_convert.h"
-}
 #include "dateformat_class.h"
 #include "dateformat_class.h"

diff --git a/ext/intl/dateformat/dateformat_attrcpp.cpp b/ext/intl/dateformat/dateformat_attrcpp.cpp
index 1c8fb88a3d5..38f90da3ab5 100644
--- a/ext/intl/dateformat/dateformat_attrcpp.cpp
+++ b/ext/intl/dateformat/dateformat_attrcpp.cpp
@@ -18,14 +18,12 @@
 #include <unicode/calendar.h>
 #include <unicode/datefmt.h>

-extern "C" {
 #include "../php_intl.h"
 #include "dateformat_class.h"
 #define USE_TIMEZONE_POINTER 1
 #include "../timezone/timezone_class.h"
 #define USE_CALENDAR_POINTER 1
 #include "../calendar/calendar_class.h"
-}

 #include "../intl_convertcpp.h"
 #include "dateformat_helpers.h"
diff --git a/ext/intl/dateformat/dateformat_class.cpp b/ext/intl/dateformat/dateformat_class.cpp
index 45a6c56cc1c..9e22ad4f419 100644
--- a/ext/intl/dateformat/dateformat_class.cpp
+++ b/ext/intl/dateformat/dateformat_class.cpp
@@ -13,13 +13,13 @@
 */
 #include <unicode/udat.h>

-extern "C" {
 #include "dateformat_class.h"
 #include "php_intl.h"
 #include "dateformat_data.h"
 #include "dateformat.h"
+BEGIN_EXTERN_C()
 #include "dateformat_arginfo.h"
-}
+END_EXTERN_C()

 #include <zend_exceptions.h>

diff --git a/ext/intl/dateformat/dateformat_class.h b/ext/intl/dateformat/dateformat_class.h
index bef8f6dd614..41d144687d1 100644
--- a/ext/intl/dateformat/dateformat_class.h
+++ b/ext/intl/dateformat/dateformat_class.h
@@ -16,15 +16,9 @@

 #include <php.h>

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "intl_common.h"
 #include "intl_error.h"
 #include "intl_data.h"
-#ifdef __cplusplus
-}
-#endif
 #include "dateformat_data.h"

 typedef struct {
@@ -39,14 +33,10 @@ typedef struct {
 #define php_intl_dateformatter_fetch_object(obj) ZEND_CONTAINER_OF(obj, IntlDateFormatter_object, zo)
 #define Z_INTL_DATEFORMATTER_P(zv) php_intl_dateformatter_fetch_object(Z_OBJ_P(zv))

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void dateformat_register_IntlDateFormatter_class( void );
 extern zend_class_entry *IntlDateFormatter_ce_ptr;
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()

 /* Auxiliary macros */

diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp
index df98c7178fc..29f20514e3c 100644
--- a/ext/intl/dateformat/dateformat_create.cpp
+++ b/ext/intl/dateformat/dateformat_create.cpp
@@ -19,7 +19,6 @@
 #include <unicode/calendar.h>
 #include <unicode/datefmt.h>

-extern "C" {
 #include <unicode/ustring.h>
 #include <unicode/udat.h>
 #include <unicode/uloc.h>
@@ -32,7 +31,6 @@ extern "C" {
 #define USE_TIMEZONE_POINTER 1
 #include "../timezone/timezone_class.h"
 #include "../intl_convert.h"
-}

 #include "dateformat_helpers.h"
 #include "zend_exceptions.h"
diff --git a/ext/intl/dateformat/dateformat_data.h b/ext/intl/dateformat/dateformat_data.h
index b93b9d78c03..8185b98ed47 100644
--- a/ext/intl/dateformat/dateformat_data.h
+++ b/ext/intl/dateformat/dateformat_data.h
@@ -18,13 +18,7 @@

 #include <unicode/udat.h>

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "intl_error.h"
-#ifdef __cplusplus
-}
-#endif

 typedef struct {
 	// error handling
@@ -34,13 +28,7 @@ typedef struct {
 	UDateFormat *  udatf;
 } dateformat_data;

-#ifdef __cplusplus
-extern "C" {
-#endif
 void dateformat_data_init( dateformat_data* datef_data );
 void dateformat_data_free( dateformat_data* datef_data );
-#ifdef __cplusplus
-}
-#endif

 #endif // DATE_FORMAT_DATA_H
diff --git a/ext/intl/dateformat/dateformat_format.cpp b/ext/intl/dateformat/dateformat_format.cpp
index 8890332dd40..19431291388 100644
--- a/ext/intl/dateformat/dateformat_format.cpp
+++ b/ext/intl/dateformat/dateformat_format.cpp
@@ -19,10 +19,8 @@
 #include <unicode/ustring.h>
 #include <unicode/unum.h>

-extern "C" {
 #include "../php_intl.h"
 #include "../intl_convert.h"
-}

 #include "../common/common_date.h"
 #include "dateformat.h"
diff --git a/ext/intl/dateformat/dateformat_format_object.cpp b/ext/intl/dateformat/dateformat_format_object.cpp
index 52199a305f0..3c115a2b5a5 100644
--- a/ext/intl/dateformat/dateformat_format_object.cpp
+++ b/ext/intl/dateformat/dateformat_format_object.cpp
@@ -23,14 +23,15 @@

 #include "../intl_convertcpp.h"

-extern "C" {
 #include "../php_intl.h"
 #include "../locale/locale.h"
 #define USE_CALENDAR_POINTER 1
 #include "../calendar/calendar_class.h"
-#include <ext/date/php_date.h>
 #include "../common/common_date.h"
-}
+
+BEGIN_EXTERN_C()
+#include <ext/date/php_date.h>
+END_EXTERN_C()

 using icu::Locale;
 using icu::DateFormat;
diff --git a/ext/intl/dateformat/dateformat_helpers.cpp b/ext/intl/dateformat/dateformat_helpers.cpp
index 5d93536807a..2b35bb5c197 100644
--- a/ext/intl/dateformat/dateformat_helpers.cpp
+++ b/ext/intl/dateformat/dateformat_helpers.cpp
@@ -21,12 +21,10 @@

 #include "dateformat_helpers.h"

-extern "C" {
 #include "../php_intl.h"
 #include <Zend/zend_operators.h>
 #define USE_CALENDAR_POINTER 1
 #include "../calendar/calendar_class.h"
-}

 // Artificial value to set for a pure proleptic gregorian calendar (until icu provides it eventually)
 #define UCAL_PHP_PROLEPTIC_GREGORIAN -16
diff --git a/ext/intl/dateformat/dateformat_helpers.h b/ext/intl/dateformat/dateformat_helpers.h
index f71e7f36870..fb2de2d9808 100644
--- a/ext/intl/dateformat/dateformat_helpers.h
+++ b/ext/intl/dateformat/dateformat_helpers.h
@@ -22,9 +22,7 @@
 #include <unicode/calendar.h>
 #include <unicode/datefmt.h>

-extern "C" {
 #include "../php_intl.h"
-}

 using icu::Locale;
 using icu::Calendar;
diff --git a/ext/intl/dateformat/dateformat_parse.cpp b/ext/intl/dateformat/dateformat_parse.cpp
index 8a554ae404d..4598a9e93c1 100644
--- a/ext/intl/dateformat/dateformat_parse.cpp
+++ b/ext/intl/dateformat/dateformat_parse.cpp
@@ -19,10 +19,8 @@
 #include <unicode/ustring.h>
 #include <math.h>

-extern "C" {
 #include "php_intl.h"
 #include "intl_convert.h"
-}
 #include "dateformat.h"
 #include "dateformat_class.h"
 #include "dateformat_data.h"
diff --git a/ext/intl/dateformat/datepatterngenerator_class.cpp b/ext/intl/dateformat/datepatterngenerator_class.cpp
index 4a137d916f1..eccf8364899 100644
--- a/ext/intl/dateformat/datepatterngenerator_class.cpp
+++ b/ext/intl/dateformat/datepatterngenerator_class.cpp
@@ -20,13 +20,13 @@

 #include <unicode/dtptngen.h>

-extern "C" {
 #define USE_DATETIMEPATTERNGENERATOR_POINTER 1
 #include "datepatterngenerator_class.h"
+BEGIN_EXTERN_C()
 #include "datepatterngenerator_arginfo.h"
+END_EXTERN_C()
 #include <zend_exceptions.h>
 #include <assert.h>
-}

 using icu::DateTimePatternGenerator;
 using icu::Locale;
@@ -97,7 +97,7 @@ static zend_object *IntlDatePatternGenerator_object_create(zend_class_entry *ce)
 /*
  * Initialize 'IntlDatePatternGenerator' class
  */
-void dateformat_register_IntlDatePatternGenerator_class( void )
+U_CFUNC void dateformat_register_IntlDatePatternGenerator_class( void )
 {
 	/* Create and register 'IntlDatePatternGenerator' class. */
 	IntlDatePatternGenerator_ce_ptr = register_class_IntlDatePatternGenerator();
diff --git a/ext/intl/dateformat/datepatterngenerator_class.h b/ext/intl/dateformat/datepatterngenerator_class.h
index c2c280e2df2..cc8526dc56b 100644
--- a/ext/intl/dateformat/datepatterngenerator_class.h
+++ b/ext/intl/dateformat/datepatterngenerator_class.h
@@ -55,10 +55,12 @@ typedef struct {
 		RETURN_THROWS(); \
 	}

+BEGIN_EXTERN_C()
 void dateformat_register_IntlDatePatternGenerator_class(void);

 extern zend_class_entry *IntlDatePatternGenerator_ce_ptr;

 extern zend_object_handlers IntlDatePatternGenerator_handlers;
+END_EXTERN_C()

 #endif /* #ifndef DATEPATTERNGENERATOR_CLASS_H */
diff --git a/ext/intl/dateformat/datepatterngenerator_methods.cpp b/ext/intl/dateformat/datepatterngenerator_methods.cpp
index 24943d4ec9b..ebebfde87ce 100644
--- a/ext/intl/dateformat/datepatterngenerator_methods.cpp
+++ b/ext/intl/dateformat/datepatterngenerator_methods.cpp
@@ -18,13 +18,11 @@

 #include "../intl_convertcpp.h"

-extern "C" {
 #include "php_intl.h"
 #define USE_DATETIMEPATTERNGENERATOR_POINTER 1
 #include "datepatterngenerator_class.h"
 #include <zend_exceptions.h>
 #include <assert.h>
-}

 using icu::DateTimePatternGenerator;
 using icu::Locale;
diff --git a/ext/intl/formatter/formatter_attr.cpp b/ext/intl/formatter/formatter_attr.cpp
index dee5a203b06..962dcf6ce21 100644
--- a/ext/intl/formatter/formatter_attr.cpp
+++ b/ext/intl/formatter/formatter_attr.cpp
@@ -20,10 +20,8 @@
 #include "../intl_convertcpp.h"
 #include "formatter_class.h"

-extern "C" {
 #include "php_intl.h"
 #include "intl_convert.h"
-}

 #define FORMATTER_UNUM(nfo) reinterpret_cast<UNumberFormat*>(FORMATTER_OBJECT(nfo))

diff --git a/ext/intl/formatter/formatter_class.cpp b/ext/intl/formatter/formatter_class.cpp
index 2f3a4bb27ee..6cf4d62f68f 100644
--- a/ext/intl/formatter/formatter_class.cpp
+++ b/ext/intl/formatter/formatter_class.cpp
@@ -13,19 +13,17 @@
  */

 #include "formatter_class.h"
-extern "C" {
 #include "php_intl.h"
 #include "formatter_data.h"
 #include "formatter_format.h"
-}

 #include <zend_exceptions.h>
 #include "Zend/zend_attributes.h"
 #include "Zend/zend_interfaces.h"

-extern "C" {
+BEGIN_EXTERN_C()
 #include "formatter_arginfo.h"
-}
+END_EXTERN_C()

 zend_class_entry *NumberFormatter_ce_ptr = NULL;
 static zend_object_handlers NumberFormatter_handlers;
diff --git a/ext/intl/formatter/formatter_class.h b/ext/intl/formatter/formatter_class.h
index 0d4a4208a16..9bd7959c89b 100644
--- a/ext/intl/formatter/formatter_class.h
+++ b/ext/intl/formatter/formatter_class.h
@@ -17,15 +17,9 @@

 #include "formatter_data.h"

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "intl_common.h"
 #include "intl_error.h"
 #include "intl_data.h"
-#ifdef __cplusplus
-}
-#endif

 typedef struct {
 	formatter_data  nf_data;
@@ -36,14 +30,10 @@ typedef struct {
 #define php_intl_number_format_fetch_object(obj) ZEND_CONTAINER_OF(obj, NumberFormatter_object, zo)
 #define Z_INTL_NUMBERFORMATTER_P(zv) php_intl_number_format_fetch_object(Z_OBJ_P(zv))

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void formatter_register_class( void );
 extern zend_class_entry *NumberFormatter_ce_ptr;
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()

 /* Auxiliary macros */

diff --git a/ext/intl/formatter/formatter_data.h b/ext/intl/formatter/formatter_data.h
index 8cacb11315c..53f2fc3e3ae 100644
--- a/ext/intl/formatter/formatter_data.h
+++ b/ext/intl/formatter/formatter_data.h
@@ -15,13 +15,7 @@
 #ifndef FORMATTER_DATA_H
 #define FORMATTER_DATA_H

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include <php.h>
-#ifdef __cplusplus
-}
-#endif

 #ifdef __cplusplus
 #include <unicode/numfmt.h>
@@ -30,13 +24,7 @@ using icu::NumberFormat;
 typedef void NumberFormat;
 #endif

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "intl_error.h"
-#ifdef __cplusplus
-}
-#endif

 typedef struct {
 	// error hangling
@@ -46,13 +34,7 @@ typedef struct {
 	NumberFormat*    unum;
 } formatter_data;

-#ifdef __cplusplus
-extern "C" {
-#endif
 void formatter_data_init( formatter_data* nf_data );
 void formatter_data_free( formatter_data* nf_data );
-#ifdef __cplusplus
-}
-#endif

 #endif // FORMATTER_DATA_H
diff --git a/ext/intl/formatter/formatter_format.cpp b/ext/intl/formatter/formatter_format.cpp
index 48edabc8ccd..f73a04ef356 100644
--- a/ext/intl/formatter/formatter_format.cpp
+++ b/ext/intl/formatter/formatter_format.cpp
@@ -22,9 +22,7 @@
 #include "formatter_class.h"
 #include "formatter_format.h"

-extern "C" {
 #include "php_intl.h"
-}

 /* {{{ Format a number. */
 U_CFUNC PHP_FUNCTION( numfmt_format )
diff --git a/ext/intl/formatter/formatter_format.h b/ext/intl/formatter/formatter_format.h
index 14aa91193ba..0872e358d97 100644
--- a/ext/intl/formatter/formatter_format.h
+++ b/ext/intl/formatter/formatter_format.h
@@ -15,8 +15,6 @@
 #ifndef FORMATTER_FORMAT_H
 #define FORMATTER_FORMAT_H

-#include <php.h>
-
 #define FORMAT_TYPE_DEFAULT	0
 #define FORMAT_TYPE_INT32	1
 #define FORMAT_TYPE_INT64	2
diff --git a/ext/intl/formatter/formatter_main.cpp b/ext/intl/formatter/formatter_main.cpp
index 79750714a5f..bbaf671db01 100644
--- a/ext/intl/formatter/formatter_main.cpp
+++ b/ext/intl/formatter/formatter_main.cpp
@@ -24,9 +24,7 @@
 #include "../intl_convertcpp.h"
 #include "formatter_class.h"

-extern "C" {
 #include "php_intl.h"
-}

 /* {{{ */
 static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
diff --git a/ext/intl/formatter/formatter_parse.cpp b/ext/intl/formatter/formatter_parse.cpp
index db7463030b7..0acab835085 100644
--- a/ext/intl/formatter/formatter_parse.cpp
+++ b/ext/intl/formatter/formatter_parse.cpp
@@ -23,10 +23,8 @@
 #include "formatter_class.h"
 #include "formatter_format.h"

-extern "C" {
 #include "php_intl.h"
 #include "intl_convert.h"
-}

 #include <locale.h>
 #include <memory>
diff --git a/ext/intl/grapheme/grapheme.h b/ext/intl/grapheme/grapheme.h
index b52f48f9d14..4da62ca0d2b 100644
--- a/ext/intl/grapheme/grapheme.h
+++ b/ext/intl/grapheme/grapheme.h
@@ -18,13 +18,9 @@
 #include <php.h>
 #include <unicode/utypes.h>

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void grapheme_close_global_iterator( void );
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()

 #define GRAPHEME_EXTRACT_TYPE_COUNT		0
 #define GRAPHEME_EXTRACT_TYPE_MAXBYTES	1
diff --git a/ext/intl/grapheme/grapheme_string.cpp b/ext/intl/grapheme/grapheme_string.cpp
index 08b41a5e6ab..4acf636d54b 100644
--- a/ext/intl/grapheme/grapheme_string.cpp
+++ b/ext/intl/grapheme/grapheme_string.cpp
@@ -22,11 +22,9 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include <php.h>
 #include "grapheme.h"
 #include "grapheme_util.h"
-}

 #include <unicode/utypes.h>
 #include <unicode/utf8.h>
diff --git a/ext/intl/grapheme/grapheme_util.cpp b/ext/intl/grapheme/grapheme_util.cpp
index 33ebde25458..bf4be3f6380 100644
--- a/ext/intl/grapheme/grapheme_util.cpp
+++ b/ext/intl/grapheme/grapheme_util.cpp
@@ -22,12 +22,10 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include <php.h>
 #include "grapheme.h"
 #include "grapheme_util.h"
 #include "intl_common.h"
-}

 #include <unicode/utypes.h>
 #include <unicode/ucol.h>
@@ -42,8 +40,7 @@ ZEND_EXTERN_MODULE_GLOBALS( intl )
 /* }}} */

 /* {{{ grapheme_close_global_iterator - clean up */
-U_CFUNC void
-grapheme_close_global_iterator( void )
+void grapheme_close_global_iterator( void )
 {
 	UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator );

@@ -54,7 +51,7 @@ grapheme_close_global_iterator( void )
 /* }}} */

 /* {{{ grapheme_substr_ascii f='from' - starting point, l='length' */
-U_CFUNC void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t l, char **sub_str, int32_t *sub_str_len)
+void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t l, char **sub_str, int32_t *sub_str_len)
 {
 	int32_t str_len2 = (int32_t)str_len; /* in order to avoid signed/unsigned problems */
 	*sub_str = NULL;
@@ -103,7 +100,7 @@ U_CFUNC void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t


 /* {{{ grapheme_strpos_utf16 - strrpos using utf16*/
-U_CFUNC int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int32_t *puchar_pos, int f_ignore_case, int last, const char* locale)
+int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int32_t *puchar_pos, int f_ignore_case, int last, const char* locale)
 {
 	UChar *uhaystack = NULL, *uneedle = NULL;
 	int32_t uhaystack_len = 0, uneedle_len = 0, char_pos, ret_pos, offset_pos = 0;
@@ -233,7 +230,7 @@ finish:
 /* }}} */

 /* {{{ grapheme_ascii_check: ASCII check */
-U_CFUNC zend_long grapheme_ascii_check(const unsigned char *day, size_t len)
+zend_long grapheme_ascii_check(const unsigned char *day, size_t len)
 {
 	int ret_len = len;
 	while ( len-- ) {
@@ -247,7 +244,7 @@ U_CFUNC zend_long grapheme_ascii_check(const unsigned char *day, size_t len)
 /* }}} */

 /* {{{ grapheme_split_string: find and optionally return grapheme boundaries */
-U_CFUNC int32_t grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len )
+int32_t grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len )
 {
 	UErrorCode		status = U_ZERO_ERROR;
 	int ret_len, pos;
@@ -284,7 +281,7 @@ U_CFUNC int32_t grapheme_split_string(const UChar *text, int32_t text_length, in
 /* }}} */

 /* {{{ grapheme_count_graphemes */
-U_CFUNC int32_t grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t string_len)
+int32_t grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t string_len)
 {
 	int ret_len = 0;
 	int pos = 0;
@@ -308,7 +305,7 @@ U_CFUNC int32_t grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int3


 /* {{{ 	grapheme_get_haystack_offset - bump the haystack pointer based on the grapheme count offset */
-U_CFUNC int32_t grapheme_get_haystack_offset(UBreakIterator* bi, int32_t offset)
+int32_t grapheme_get_haystack_offset(UBreakIterator* bi, int32_t offset)
 {
 	int32_t pos;
 	int32_t (*iter_op)(UBreakIterator* bi);
@@ -348,7 +345,7 @@ U_CFUNC int32_t grapheme_get_haystack_offset(UBreakIterator* bi, int32_t offset)
 /* }}} */

 /* {{{ grapheme_strrpos_ascii: borrowed from the php ext/standard/string.c */
-U_CFUNC zend_long grapheme_strrpos_ascii(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset)
+zend_long grapheme_strrpos_ascii(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset)
 {
 	char *p, *e;

@@ -388,7 +385,7 @@ U_CFUNC zend_long grapheme_strrpos_ascii(char *haystack, size_t haystack_len, ch
 /* }}} */

 /* {{{ grapheme_get_break_iterator: get a clone of the global character break iterator */
-U_CFUNC UBreakIterator* grapheme_get_break_iterator(UErrorCode *status )
+UBreakIterator* grapheme_get_break_iterator(UErrorCode *status )
 {
 	UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator );

diff --git a/ext/intl/grapheme/grapheme_util.h b/ext/intl/grapheme/grapheme_util.h
index 0ddfcd3da88..14ff800abdc 100644
--- a/ext/intl/grapheme/grapheme_util.h
+++ b/ext/intl/grapheme/grapheme_util.h
@@ -15,9 +15,6 @@
 #ifndef GRAPHEME_GRAPHEME_UTIL_H
 #define GRAPHEME_GRAPHEME_UTIL_H

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "php_intl.h"
 #include "intl_convert.h"

@@ -38,9 +35,6 @@ int32_t grapheme_count_graphemes(UBreakIterator *bi, UChar *string, int32_t stri
 int32_t grapheme_get_haystack_offset(UBreakIterator* bi, int32_t offset);

 UBreakIterator* grapheme_get_break_iterator(UErrorCode *status );
-#ifdef __cplusplus
-}
-#endif

 /* OUTSIDE_STRING: check if (possibly negative) long offset is outside the string with int32_t length */
 #define OUTSIDE_STRING(offset, max_len) ( offset <= INT32_MIN || offset > INT32_MAX || (offset < 0 ? -offset > (zend_long) max_len : offset > (zend_long) max_len) )
diff --git a/ext/intl/idn/idn.cpp b/ext/intl/idn/idn.cpp
index c1db9a84ccd..3f6cbc3ec8a 100644
--- a/ext/intl/idn/idn.cpp
+++ b/ext/intl/idn/idn.cpp
@@ -18,17 +18,13 @@
 #include <config.h>
 #endif

-extern "C" {
 #include "../php_intl.h"
-}
 #include <unicode/uidna.h>
 #include <unicode/ustring.h>

 #include "idn.h"

-extern "C" {
 #include "intl_error.h"
-}
 /* }}} */

 enum {
diff --git a/ext/intl/intl_convert.h b/ext/intl/intl_convert.h
index f33746b00c9..c3328cb8c33 100644
--- a/ext/intl/intl_convert.h
+++ b/ext/intl/intl_convert.h
@@ -18,6 +18,7 @@

 #include <unicode/ustring.h>

+BEGIN_EXTERN_C()
 void intl_convert_utf8_to_utf16(
 	UChar**     target, int32_t* target_len,
 	const char* src,    size_t  src_len,
@@ -38,5 +39,6 @@ bool intl_convert_utf8_offset_to_utf16(
 int32_t intl_convert_utf16_offset_to_utf8(
 	const UChar* str, int32_t  str_len,
 	int32_t      position );
+END_EXTERN_C()

 #endif // INTL_CONVERT_H
diff --git a/ext/intl/intl_convertcpp.cpp b/ext/intl/intl_convertcpp.cpp
index b305ff201c7..e8ad587c268 100644
--- a/ext/intl/intl_convertcpp.cpp
+++ b/ext/intl/intl_convertcpp.cpp
@@ -16,9 +16,7 @@

 #include "intl_convertcpp.h"
 #include <unicode/ustring.h>
-extern "C" {
 #include <php.h>
-}

 /* {{{ intl_stringFromChar */
 int intl_stringFromChar(UnicodeString &ret, char *str, size_t str_len, UErrorCode *status)
diff --git a/ext/intl/intl_error.h b/ext/intl/intl_error.h
index 54fa0bf86f1..7559281b19a 100644
--- a/ext/intl/intl_error.h
+++ b/ext/intl/intl_error.h
@@ -23,6 +23,8 @@

 #define INTL_ERROR_CODE(e) (e).code

+BEGIN_EXTERN_C()
+
 typedef struct {
 	zend_string *custom_error_message;
 	UErrorCode   code;
@@ -45,4 +47,6 @@ void        intl_errors_set( intl_error* err, UErrorCode code, const char* msg);
 // Other error helpers
 smart_str	intl_parse_error_to_string( UParseError* pe );

+END_EXTERN_C()
+
 #endif // INTL_ERROR_H
diff --git a/ext/intl/intl_icu_compat.h b/ext/intl/intl_icu_compat.h
index ae3a6aa126e..f7a17e5a6bf 100644
--- a/ext/intl/intl_icu_compat.h
+++ b/ext/intl/intl_icu_compat.h
@@ -36,21 +36,13 @@ typedef USpoofCheckResult IntlIcuSpoofCheckResult;
 typedef void IntlIcuSpoofCheckResult;
 #endif

-#ifdef __cplusplus
-extern "C" {
-#endif
-
-UConverter *intl_icu_compat_ucnv_clone(const UConverter *converter, UErrorCode *status);
-UBreakIterator *intl_icu_compat_ubrk_clone(const UBreakIterator *break_iterator, UErrorCode *status);
-void intl_icu_compat_uspoof_init_checker(USpoofChecker *checker, IntlIcuSpoofCheckResult **check_result, UErrorCode *status);
-void intl_icu_compat_uspoof_close_check_result(IntlIcuSpoofCheckResult *check_result);
-int32_t intl_icu_compat_uspoof_check_utf8(const USpoofChecker *checker, const char *text, int32_t length, IntlIcuSpoofCheckResult *check_result, UErrorCode *status);
-UBool intl_icu_compat_uspoof_check_result_mismatch(IntlIcuSpoofCheckResult *check_result, int32_t checks, int32_t *result_checks, UErrorCode *status);
-UBool intl_icu_compat_uspoof_is_allowed_chars_pattern_option(int64_t pattern_option);
-const char *intl_icu_compat_uspoof_allowed_chars_pattern_option_error_message(void);
-
-#ifdef __cplusplus
-}
-#endif
+U_CFUNC UConverter *intl_icu_compat_ucnv_clone(const UConverter *converter, UErrorCode *status);
+U_CFUNC UBreakIterator *intl_icu_compat_ubrk_clone(const UBreakIterator *break_iterator, UErrorCode *status);
+U_CFUNC void intl_icu_compat_uspoof_init_checker(USpoofChecker *checker, IntlIcuSpoofCheckResult **check_result, UErrorCode *status);
+U_CFUNC void intl_icu_compat_uspoof_close_check_result(IntlIcuSpoofCheckResult *check_result);
+U_CFUNC int32_t intl_icu_compat_uspoof_check_utf8(const USpoofChecker *checker, const char *text, int32_t length, IntlIcuSpoofCheckResult *check_result, UErrorCode *status);
+U_CFUNC UBool intl_icu_compat_uspoof_check_result_mismatch(IntlIcuSpoofCheckResult *check_result, int32_t checks, int32_t *result_checks, UErrorCode *status);
+U_CFUNC UBool intl_icu_compat_uspoof_is_allowed_chars_pattern_option(int64_t pattern_option);
+U_CFUNC const char *intl_icu_compat_uspoof_allowed_chars_pattern_option_error_message(void);

 #endif
diff --git a/ext/intl/listformatter/listformatter_class.cpp b/ext/intl/listformatter/listformatter_class.cpp
index 87b5efb3f66..10ec6053dc8 100644
--- a/ext/intl/listformatter/listformatter_class.cpp
+++ b/ext/intl/listformatter/listformatter_class.cpp
@@ -12,19 +12,17 @@
    +----------------------------------------------------------------------+
 */

-extern "C" {
 #include "php.h"
-}

 #include <unicode/listformatter.h>
 #include <unicode/locid.h>
 #include "../intl_convertcpp.h"

-extern "C" {
 #include "php_intl.h"
-}
 #include "listformatter_class.h"
+BEGIN_EXTERN_C()
 #include "listformatter_arginfo.h"
+END_EXTERN_C()

 #include <memory>

@@ -210,7 +208,7 @@ PHP_METHOD(IntlListFormatter, getErrorMessage)
     RETURN_STR(message);
 }

-void listformatter_register_class(void)
+U_CFUNC void listformatter_register_class(void)
 {
     zend_class_entry *class_entry = register_class_IntlListFormatter();
     class_entry->create_object = listformatter_create_object;
diff --git a/ext/intl/listformatter/listformatter_class.h b/ext/intl/listformatter/listformatter_class.h
index bdf21b6886e..e0d767b6e71 100644
--- a/ext/intl/listformatter/listformatter_class.h
+++ b/ext/intl/listformatter/listformatter_class.h
@@ -49,14 +49,10 @@ typedef struct {

 #define LISTFORMATTER_OBJECT(lfo) (lfo)->lf_data.ulistfmt

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void listformatter_register_class( void );
+END_EXTERN_C()
 extern zend_class_entry *ListFormatter_ce_ptr;
-#ifdef __cplusplus
-}
-#endif

 #define INTL_LISTFORMATTER_FALLBACK_TYPE_AND 0
 #define INTL_LISTFORMATTER_FALLBACK_WIDTH_WIDE 0
diff --git a/ext/intl/locale/locale_class.cpp b/ext/intl/locale/locale_class.cpp
index a8d34f2e9f2..3629a4dddb8 100644
--- a/ext/intl/locale/locale_class.cpp
+++ b/ext/intl/locale/locale_class.cpp
@@ -13,13 +13,13 @@
 */

 #include <unicode/uloc.h>
-extern "C" {
 #include "php_intl.h"
 #include "intl_error.h"
 #include "locale_class.h"
 #include "locale.h"
+BEGIN_EXTERN_C()
 #include "locale_arginfo.h"
-}
+END_EXTERN_C()

 zend_class_entry *Locale_ce_ptr = NULL;

diff --git a/ext/intl/locale/locale_methods.cpp b/ext/intl/locale/locale_methods.cpp
index 8130593b893..5fd89c62f15 100644
--- a/ext/intl/locale/locale_methods.cpp
+++ b/ext/intl/locale/locale_methods.cpp
@@ -25,7 +25,6 @@
 #include <unicode/uenum.h>
 #include <unicode/locid.h>

-extern "C" {
 #include "php_intl.h"
 #include "locale.h"
 #include "locale_class.h"
@@ -37,7 +36,6 @@ extern "C" {
 #include <php.h>
 #include "main/php_ini.h"
 #include "zend_smart_str.h"
-}

 ZEND_EXTERN_MODULE_GLOBALS( intl )

diff --git a/ext/intl/msgformat/msgformat.cpp b/ext/intl/msgformat/msgformat.cpp
index 3857e97b4a4..2f25256f03f 100644
--- a/ext/intl/msgformat/msgformat.cpp
+++ b/ext/intl/msgformat/msgformat.cpp
@@ -19,12 +19,10 @@
 #include <unicode/ustring.h>
 #include <unicode/umsg.h>

-extern "C" {
 #include "php_intl.h"
 #include "msgformat_class.h"
 #include "msgformat_data.h"
 #include "intl_convert.h"
-}

 /* {{{ */
 static int msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
diff --git a/ext/intl/msgformat/msgformat_attr.cpp b/ext/intl/msgformat/msgformat_attr.cpp
index 15c3525b858..bb7b2164015 100644
--- a/ext/intl/msgformat/msgformat_attr.cpp
+++ b/ext/intl/msgformat/msgformat_attr.cpp
@@ -16,12 +16,10 @@
 #include <config.h>
 #endif

-extern "C" {
 #include "php_intl.h"
 #include "msgformat_class.h"
 #include "msgformat_data.h"
 #include "intl_convert.h"
-}

 #include <unicode/ustring.h>

diff --git a/ext/intl/msgformat/msgformat_class.cpp b/ext/intl/msgformat/msgformat_class.cpp
index 79398fb76e1..a31de93007f 100644
--- a/ext/intl/msgformat/msgformat_class.cpp
+++ b/ext/intl/msgformat/msgformat_class.cpp
@@ -14,12 +14,13 @@

 #include <unicode/unum.h>

-extern "C" {
 #include "msgformat_class.h"
 #include "php_intl.h"
 #include "msgformat_data.h"
+
+BEGIN_EXTERN_C()
 #include "msgformat_arginfo.h"
-}
+END_EXTERN_C()

 #include <zend_exceptions.h>

diff --git a/ext/intl/msgformat/msgformat_class.h b/ext/intl/msgformat/msgformat_class.h
index 849c45c1472..2024723e24c 100644
--- a/ext/intl/msgformat/msgformat_class.h
+++ b/ext/intl/msgformat/msgformat_class.h
@@ -33,9 +33,10 @@ typedef struct {
 #define php_intl_messageformatter_fetch_object(obj) ZEND_CONTAINER_OF(obj, MessageFormatter_object, zo)
 #define Z_INTL_MESSAGEFORMATTER_P(zv) php_intl_messageformatter_fetch_object(Z_OBJ_P(zv))

+BEGIN_EXTERN_C()
 void msgformat_register_class( void );
 extern zend_class_entry *MessageFormatter_ce_ptr;
-
+END_EXTERN_C()
 /* Auxiliary macros */

 #define MSG_FORMAT_METHOD_INIT_VARS		INTL_METHOD_INIT_VARS(MessageFormatter, mfo)
diff --git a/ext/intl/msgformat/msgformat_data.cpp b/ext/intl/msgformat/msgformat_data.cpp
index f36bf9e4ac7..0a059a9ea48 100644
--- a/ext/intl/msgformat/msgformat_data.cpp
+++ b/ext/intl/msgformat/msgformat_data.cpp
@@ -24,7 +24,7 @@
 /* {{{ void msgformat_data_init( msgformat_data* mf_data )
  * Initialize internals of msgformat_data.
  */
-U_CFUNC void msgformat_data_init( msgformat_data* mf_data )
+void msgformat_data_init( msgformat_data* mf_data )
 {
 	if( !mf_data )
 		return;
@@ -40,7 +40,7 @@ U_CFUNC void msgformat_data_init( msgformat_data* mf_data )
 /* {{{ void msgformat_data_free( msgformat_data* mf_data )
  * Clean up memory allocated for msgformat_data
  */
-U_CFUNC void msgformat_data_free(msgformat_data* mf_data)
+void msgformat_data_free(msgformat_data* mf_data)
 {
 	if (!mf_data)
 		return;
diff --git a/ext/intl/msgformat/msgformat_data.h b/ext/intl/msgformat/msgformat_data.h
index 7ca4a5acb1a..ca24a14cb0b 100644
--- a/ext/intl/msgformat/msgformat_data.h
+++ b/ext/intl/msgformat/msgformat_data.h
@@ -17,13 +17,7 @@

 #include <php.h>

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "../intl_error.h"
-#ifdef __cplusplus
-}
-#endif

 #include <unicode/umsg.h>

@@ -39,14 +33,8 @@ typedef struct {
 	int				tz_set; /* if we've already the time zone in sub-formats */
 } msgformat_data;

-#ifdef __cplusplus
-extern "C" {
-#endif
 void msgformat_data_init( msgformat_data* mf_data );
 void msgformat_data_free( msgformat_data* mf_data );
-#ifdef __cplusplus
-}
-#endif

 #ifdef MSG_FORMAT_QUOTE_APOS
 int msgformat_fix_quotes(UChar **spattern, uint32_t *spattern_len, UErrorCode *ec);
diff --git a/ext/intl/msgformat/msgformat_format.cpp b/ext/intl/msgformat/msgformat_format.cpp
index c0a02ad8db1..d4f2186e587 100644
--- a/ext/intl/msgformat/msgformat_format.cpp
+++ b/ext/intl/msgformat/msgformat_format.cpp
@@ -18,13 +18,11 @@

 #include <unicode/ustring.h>

-extern "C" {
 #include "php_intl.h"
 #include "msgformat_class.h"
 #include "msgformat_data.h"
 #include "msgformat_helpers.h"
 #include "intl_convert.h"
-}

 #ifndef Z_ADDREF_P
 #define Z_ADDREF_P(z) ((z)->refcount++)
diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp
index b7d592641bd..d079703c2ec 100644
--- a/ext/intl/msgformat/msgformat_helpers.cpp
+++ b/ext/intl/msgformat/msgformat_helpers.cpp
@@ -31,14 +31,12 @@
 #include "../intl_convertcpp.h"
 #include "../common/common_date.h"

-extern "C" {
 #include "php_intl.h"
 #include "msgformat_class.h"
 #include "msgformat_helpers.h"
 #include "intl_convert.h"
 #define USE_TIMEZONE_POINTER
 #include "../timezone/timezone_class.h"
-}

 U_NAMESPACE_BEGIN
 /**
@@ -351,7 +349,7 @@ static void umsg_set_timezone(MessageFormatter_object *mfo,
   }
 }

-U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo,
+void umsg_format_helper(MessageFormatter_object *mfo,
 								HashTable *args,
 								UChar **formatted,
 								int32_t *formatted_len)
@@ -607,7 +605,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo,

 #define cleanup_zvals() for(int j=i;j>=0;j--) { zval_ptr_dtor((*args)+i); }

-U_CFUNC void umsg_parse_helper(UMessageFormat *fmt, int *count, zval **args, UChar *source, int32_t source_len, UErrorCode *status)
+void umsg_parse_helper(UMessageFormat *fmt, int *count, zval **args, UChar *source, int32_t source_len, UErrorCode *status)
 {
     UnicodeString srcString(source, source_len);
     Formattable *fargs = ((const MessageFormat*)fmt)->parse(srcString, *count, *status);
diff --git a/ext/intl/msgformat/msgformat_parse.cpp b/ext/intl/msgformat/msgformat_parse.cpp
index e177d3aca7f..a9dc1314a22 100644
--- a/ext/intl/msgformat/msgformat_parse.cpp
+++ b/ext/intl/msgformat/msgformat_parse.cpp
@@ -18,13 +18,11 @@

 #include <unicode/ustring.h>

-extern "C" {
 #include "php_intl.h"
 #include "msgformat_class.h"
 #include "msgformat_data.h"
 #include "msgformat_helpers.h"
 #include "intl_convert.h"
-}

 /* {{{ */
 static void msgfmt_do_parse(MessageFormatter_object *mfo, const char *source, size_t src_len, zval *return_value)
diff --git a/ext/intl/normalizer/normalizer_class.cpp b/ext/intl/normalizer/normalizer_class.cpp
index 1898df04e2e..d837c311530 100644
--- a/ext/intl/normalizer/normalizer_class.cpp
+++ b/ext/intl/normalizer/normalizer_class.cpp
@@ -20,14 +20,10 @@
 #include "normalizer.h"
 #include "normalizer_class.h"
 #include "php_intl.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 #include "normalizer_arginfo.h"
+END_EXTERN_C()
 #include "intl_error.h"
-#ifdef __cplusplus
-}
-#endif

 #include <unicode/unorm.h>

diff --git a/ext/intl/normalizer/normalizer_class.h b/ext/intl/normalizer/normalizer_class.h
index e30c2923704..ec1d6be21bf 100644
--- a/ext/intl/normalizer/normalizer_class.h
+++ b/ext/intl/normalizer/normalizer_class.h
@@ -36,12 +36,9 @@ typedef struct {
 #define NORMALIZER_ERROR_CODE(co)   INTL_ERROR_CODE(NORMALIZER_ERROR(co))
 #define NORMALIZER_ERROR_CODE_P(co) &(INTL_ERROR_CODE(NORMALIZER_ERROR(co)))

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void normalizer_register_Normalizer_class( void );
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()
+
 extern zend_class_entry *Normalizer_ce_ptr;
 #endif // #ifndef NORMALIZER_CLASS_H
diff --git a/ext/intl/normalizer/normalizer_normalize.cpp b/ext/intl/normalizer/normalizer_normalize.cpp
index de9693580b1..ceaf2aaba48 100644
--- a/ext/intl/normalizer/normalizer_normalize.cpp
+++ b/ext/intl/normalizer/normalizer_normalize.cpp
@@ -21,13 +21,11 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
 #include <unicode/unorm2.h>
 #include "normalizer.h"
 #include "normalizer_class.h"
 #include "intl_convert.h"
-}
 #include <unicode/utf8.h>


diff --git a/ext/intl/numberformatter/numberformatter_class.cpp b/ext/intl/numberformatter/numberformatter_class.cpp
index 71427da58ae..cc98c075f56 100644
--- a/ext/intl/numberformatter/numberformatter_class.cpp
+++ b/ext/intl/numberformatter/numberformatter_class.cpp
@@ -12,22 +12,20 @@
    +----------------------------------------------------------------------+
 */

-extern "C" {
 #include "php.h"
 #include "zend_API.h"
 #include "../intl_common.h"
-}

 #if U_ICU_VERSION_MAJOR_NUM >= 63
 #include <unicode/numberformatter.h>
 #include <unicode/unistr.h>
 #include <unicode/locid.h>
 #include "../intl_convertcpp.h"
-
-extern "C" {
 #include "../php_intl.h"
+
+BEGIN_EXTERN_C()
 #include "numberformatter_arginfo.h"
-}
+END_EXTERN_C()
 #include "numberformatter_class.h"

 using icu::number::NumberFormatter;
diff --git a/ext/intl/numberformatter/numberformatter_class.h b/ext/intl/numberformatter/numberformatter_class.h
index 79ec5895ac5..4bd6332465e 100644
--- a/ext/intl/numberformatter/numberformatter_class.h
+++ b/ext/intl/numberformatter/numberformatter_class.h
@@ -15,16 +15,10 @@
 #ifndef NUMBERFORMATTER_CLASS_H
 #define NUMBERFORMATTER_CLASS_H

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include <php.h>
 #include "intl_common.h"
 #include "intl_error.h"
 #include "intl_data.h"
-#ifdef __cplusplus
-}
-#endif

 #ifdef __cplusplus
 #include <unicode/numberformatter.h>
@@ -48,13 +42,9 @@ typedef struct {

 #define NUMBERFORMATTER_OBJECT(nfo) (nfo)->nf_data.unumf

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void numberformatter_register_class(void);
 extern zend_class_entry *IntlNumberFormatter_ce_ptr;
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()

 #endif
diff --git a/ext/intl/php_intl.h b/ext/intl/php_intl.h
index 52f80d48e3a..58a822de0be 100644
--- a/ext/intl/php_intl.h
+++ b/ext/intl/php_intl.h
@@ -20,9 +20,6 @@

 #include <php.h>

-/* Even if we're included from C++, don't introduce C++ definitions
- * because we were included with extern "C". The effect would be that
- * when the headers defined any method, they would do so with C linkage */
 #undef U_SHOW_CPLUSPLUS_API
 #define U_SHOW_CPLUSPLUS_API 0
 #include "collator/collator_sort.h"
@@ -43,6 +40,7 @@ extern zend_module_entry intl_module_entry;
 #include "TSRM.h"
 #endif

+BEGIN_EXTERN_C()
 ZEND_BEGIN_MODULE_GLOBALS(intl)
 	struct UCollator *current_collator;
 	intl_error *current_collator_error;
@@ -71,6 +69,8 @@ PHP_MINFO_FUNCTION(intl);
 const char *intl_locale_get_default( void );
 char *canonicalize_locale_string(const char* locale);

+END_EXTERN_C()
+
 #define PHP_INTL_FUNCTION_WITH_ERROR_RESET(name) \
 	static void php_intl_##name##_impl(INTERNAL_FUNCTION_PARAMETERS); \
 	U_CFUNC PHP_FUNCTION(name) \
diff --git a/ext/intl/rangeformatter/rangeformatter_class.cpp b/ext/intl/rangeformatter/rangeformatter_class.cpp
index 37b49e4f131..1291d17b37b 100644
--- a/ext/intl/rangeformatter/rangeformatter_class.cpp
+++ b/ext/intl/rangeformatter/rangeformatter_class.cpp
@@ -12,11 +12,9 @@
    +----------------------------------------------------------------------+
 */

-extern "C" {
-    #include "php.h"
-    #include "zend_API.h"
-    #include "../intl_common.h"
-}
+#include "php.h"
+#include "zend_API.h"
+#include "../intl_common.h"

 #if U_ICU_VERSION_MAJOR_NUM >= 63
 #include <unicode/numberrangeformatter.h>
@@ -25,13 +23,15 @@ extern "C" {
 #include <unicode/locid.h>
 #include "../intl_convertcpp.h"

-extern "C" {
-    #include "../intl_error.h"
-    #include "../php_intl.h"
-    #include "../intl_data.h"
-    #include "rangeformatter_arginfo.h"
-    #include "rangeformatter_class.h"
-}
+#include "../intl_error.h"
+#include "../php_intl.h"
+#include "../intl_data.h"
+
+BEGIN_EXTERN_C()
+#include "rangeformatter_arginfo.h"
+END_EXTERN_C()
+
+#include "rangeformatter_class.h"

 using icu::number::NumberRangeFormatter;
 using icu::number::NumberFormatter;
@@ -244,7 +244,7 @@ void IntlNumberRangeFormatter_object_free(zend_object *object)
     zend_object_std_dtor(&nfo->zo);
 }

-void rangeformatter_register_class(void)
+U_CFUNC void rangeformatter_register_class(void)
 {
     class_entry_IntlNumberRangeFormatter = register_class_IntlNumberRangeFormatter();
     class_entry_IntlNumberRangeFormatter->create_object = IntlNumberRangeFormatter_object_create;
diff --git a/ext/intl/rangeformatter/rangeformatter_class.h b/ext/intl/rangeformatter/rangeformatter_class.h
index 4b6f02dc93c..fc36a8bcb96 100644
--- a/ext/intl/rangeformatter/rangeformatter_class.h
+++ b/ext/intl/rangeformatter/rangeformatter_class.h
@@ -44,7 +44,8 @@ typedef struct {

 #define RANGEFORMATTER_OBJECT(nfo) (nfo)->nrf_data.unumrf

-
+BEGIN_EXTERN_C()
 void rangeformatter_register_class(void);
+END_EXTERN_C()

 #endif
diff --git a/ext/intl/reldateformatter/reldateformatter_class.cpp b/ext/intl/reldateformatter/reldateformatter_class.cpp
index e2b5db0b7b0..41a1fedca84 100644
--- a/ext/intl/reldateformatter/reldateformatter_class.cpp
+++ b/ext/intl/reldateformatter/reldateformatter_class.cpp
@@ -12,11 +12,9 @@
    +----------------------------------------------------------------------+
  */

-extern "C" {
 #include "php.h"
 #include "zend_enum.h"
 #include "zend_exceptions.h"
-}

 #include "../formatter/formatter_class.h"

@@ -32,11 +30,9 @@ extern "C" {
 #include <memory>
 #include <new>

-extern "C" {
 #include "../php_intl.h"
 #include "../intl_data.h"
 #include "../intl_error.h"
-}

 #include "../intl_convertcpp.h"
 #include "reldateformatter_class.h"
diff --git a/ext/intl/reldateformatter/reldateformatter_class.h b/ext/intl/reldateformatter/reldateformatter_class.h
index cd2ddc6e32e..5d39a30e95b 100644
--- a/ext/intl/reldateformatter/reldateformatter_class.h
+++ b/ext/intl/reldateformatter/reldateformatter_class.h
@@ -42,15 +42,9 @@ typedef struct {
 #define RELDATEFORMATTER_ERROR_P(obj) (&RELDATEFORMATTER_ERROR(obj))
 #define RELDATEFORMATTER_OBJECT(obj) ((obj)->formatter)

-#ifdef __cplusplus
-extern "C" {
-#endif
-
+BEGIN_EXTERN_C()
 void reldateformatter_register_class(void);
 extern zend_class_entry *IntlRelativeDateTimeFormatter_ce_ptr;
-
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()

 #endif /* RELDATEFORMATTER_CLASS_H */
diff --git a/ext/intl/resourcebundle/resourcebundle.cpp b/ext/intl/resourcebundle/resourcebundle.cpp
index d3a41b7c8d9..4674037e72f 100644
--- a/ext/intl/resourcebundle/resourcebundle.cpp
+++ b/ext/intl/resourcebundle/resourcebundle.cpp
@@ -17,14 +17,12 @@
 #include <zend.h>
 #include <zend_API.h>

-extern "C" {
 #include "intl_convert.h"
 #include "intl_data.h"
 #include "resourcebundle/resourcebundle_class.h"
-}

 /* {{{ ResourceBundle_extract_value */
-U_CFUNC void resourcebundle_extract_value( zval *return_value, ResourceBundle_object *source )
+void resourcebundle_extract_value( zval *return_value, ResourceBundle_object *source )
 {
 	UResType               restype;
 	const UChar*           ufield;
diff --git a/ext/intl/resourcebundle/resourcebundle.h b/ext/intl/resourcebundle/resourcebundle.h
index e7c79c480d3..c52b83c4ccb 100644
--- a/ext/intl/resourcebundle/resourcebundle.h
+++ b/ext/intl/resourcebundle/resourcebundle.h
@@ -21,12 +21,6 @@

 #include "resourcebundle/resourcebundle_class.h"

-#ifdef __cplusplus
-extern "C" {
-#endif
 void resourcebundle_extract_value( zval *target, ResourceBundle_object *source);
-#ifdef __cplusplus
-}
-#endif

 #endif // #ifndef RESOURCEBUNDLE_CLASS_H
diff --git a/ext/intl/resourcebundle/resourcebundle_class.cpp b/ext/intl/resourcebundle/resourcebundle_class.cpp
index a7ca5eceeaa..a18a23c3a87 100644
--- a/ext/intl/resourcebundle/resourcebundle_class.cpp
+++ b/ext/intl/resourcebundle/resourcebundle_class.cpp
@@ -16,24 +16,20 @@
 #include <unicode/ures.h>
 #include <unicode/uenum.h>

-
-extern "C" {
-#include <zend.h>
 #include <php.h>
-}

 #include <Zend/zend_exceptions.h>
 #include <Zend/zend_interfaces.h>

-extern "C" {
 #include "php_intl.h"
 #include "intl_data.h"
 #include "intl_common.h"
 #include "resourcebundle/resourcebundle.h"
 #include "resourcebundle/resourcebundle_iterator.h"
 #include "resourcebundle/resourcebundle_class.h"
+BEGIN_EXTERN_C()
 #include "resourcebundle/resourcebundle_arginfo.h"
-}
+END_EXTERN_C()

 zend_class_entry *ResourceBundle_ce_ptr = NULL;

diff --git a/ext/intl/resourcebundle/resourcebundle_class.h b/ext/intl/resourcebundle/resourcebundle_class.h
index 1ec2ac59222..febb4c5ae70 100644
--- a/ext/intl/resourcebundle/resourcebundle_class.h
+++ b/ext/intl/resourcebundle/resourcebundle_class.h
@@ -18,14 +18,10 @@
 #include <unicode/ures.h>

 #include <zend.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+
 #include "php.h"
 #include "intl_error.h"
-#ifdef __cplusplus
-}
-#endif
+

 typedef struct {
 	intl_error      error;
@@ -51,13 +47,9 @@ static inline ResourceBundle_object *php_intl_resourcebundle_fetch_object(zend_o

 #define RESOURCEBUNDLE_OBJECT(rb)			(rb)->me

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void resourcebundle_register_class( void );
 extern zend_class_entry *ResourceBundle_ce_ptr;
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()

 #endif // #ifndef RESOURCEBUNDLE_CLASS_H
diff --git a/ext/intl/resourcebundle/resourcebundle_iterator.cpp b/ext/intl/resourcebundle/resourcebundle_iterator.cpp
index 29288418437..1ff2f666766 100644
--- a/ext/intl/resourcebundle/resourcebundle_iterator.cpp
+++ b/ext/intl/resourcebundle/resourcebundle_iterator.cpp
@@ -12,11 +12,9 @@
    +----------------------------------------------------------------------+
  */

-extern "C" {
 #include <php.h>
 #include <zend.h>
 #include <zend_API.h>
-}

 #include "resourcebundle/resourcebundle.h"
 #include "resourcebundle/resourcebundle_class.h"
diff --git a/ext/intl/resourcebundle/resourcebundle_iterator.h b/ext/intl/resourcebundle/resourcebundle_iterator.h
index 762c12f363b..3eab1f09981 100644
--- a/ext/intl/resourcebundle/resourcebundle_iterator.h
+++ b/ext/intl/resourcebundle/resourcebundle_iterator.h
@@ -29,12 +29,6 @@ typedef struct {
 	zend_long             i;
 } ResourceBundle_iterator;

-#ifdef __cplusplus
-extern "C" {
-#endif
-zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref );
-#ifdef __cplusplus
-}
-#endif
+U_CFUNC zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref );

 #endif // #ifndef RESOURCEBUNDLE_ITERATOR_H
diff --git a/ext/intl/spoofchecker/spoofchecker_class.cpp b/ext/intl/spoofchecker/spoofchecker_class.cpp
index fcadb2f4480..317b844e993 100644
--- a/ext/intl/spoofchecker/spoofchecker_class.cpp
+++ b/ext/intl/spoofchecker/spoofchecker_class.cpp
@@ -13,14 +13,15 @@
  */

 #include "spoofchecker_class.h"
-extern "C" {
-#include "spoofchecker_arginfo.h"
 #include "php_intl.h"
 #include "intl_error.h"
-}

 #include <unicode/uspoof.h>

+BEGIN_EXTERN_C()
+#include "spoofchecker_arginfo.h"
+END_EXTERN_C()
+
 zend_class_entry *Spoofchecker_ce_ptr = NULL;
 static zend_object_handlers Spoofchecker_handlers;

@@ -66,7 +67,6 @@ static zend_object *Spoofchecker_object_create(zend_class_entry *ce)

 	return &intern->zo;
 }
-/* }}} */

 /*
  * 'Spoofchecker' class registration structures & functions
diff --git a/ext/intl/spoofchecker/spoofchecker_class.h b/ext/intl/spoofchecker/spoofchecker_class.h
index dc9aa43db8a..b8080ab84c6 100644
--- a/ext/intl/spoofchecker/spoofchecker_class.h
+++ b/ext/intl/spoofchecker/spoofchecker_class.h
@@ -17,15 +17,9 @@

 #include <php.h>

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "intl_common.h"
 #include "intl_error.h"
 #include "intl_data.h"
-#ifdef __cplusplus
-}
-#endif

 #include "intl_icu_compat.h"
 #include <unicode/uspoof.h>
@@ -50,15 +44,11 @@ typedef struct {
 #define SPOOFCHECKER_ERROR_CODE(co)   INTL_ERROR_CODE(SPOOFCHECKER_ERROR(co))
 #define SPOOFCHECKER_ERROR_CODE_P(co) &(INTL_ERROR_CODE(SPOOFCHECKER_ERROR(co)))

-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 void spoofchecker_register_Spoofchecker_class(void);
-#ifdef __cplusplus
-}
-#endif

 extern zend_class_entry *Spoofchecker_ce_ptr;
+END_EXTERN_C()

 /* Auxiliary macros */

diff --git a/ext/intl/spoofchecker/spoofchecker_create.cpp b/ext/intl/spoofchecker/spoofchecker_create.cpp
index 8a322c0d64c..9dbd2a6eac0 100644
--- a/ext/intl/spoofchecker/spoofchecker_create.cpp
+++ b/ext/intl/spoofchecker/spoofchecker_create.cpp
@@ -21,10 +21,8 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
 #include "intl_data.h"
-}
 #include "spoofchecker_class.h"

 /* {{{ Spoofchecker object constructor. */
diff --git a/ext/intl/spoofchecker/spoofchecker_main.cpp b/ext/intl/spoofchecker/spoofchecker_main.cpp
index 7a3ffd9b809..92c7bb44de5 100644
--- a/ext/intl/spoofchecker/spoofchecker_main.cpp
+++ b/ext/intl/spoofchecker/spoofchecker_main.cpp
@@ -21,10 +21,8 @@
 #include <unicode/unistr.h>
 #endif

-extern "C" {
 #include "php_intl.h"
 #include "intl_convert.h"
-}
 #include "spoofchecker_class.h"

 /* {{{ Checks if a given text contains any suspicious characters */
diff --git a/ext/intl/timezone/timezone_class.cpp b/ext/intl/timezone/timezone_class.cpp
index 23b5511cf36..aa1978e70d7 100644
--- a/ext/intl/timezone/timezone_class.cpp
+++ b/ext/intl/timezone/timezone_class.cpp
@@ -27,15 +27,15 @@

 #include "../common/common_date.h"

-extern "C" {
 #include "../intl_convert.h"
 #define USE_TIMEZONE_POINTER 1
 #include "timezone_class.h"
-#include "timezone_arginfo.h"
 #include <zend_exceptions.h>
 #include <zend_interfaces.h>
+U_CDECL_BEGIN
+#include "timezone_arginfo.h"
 #include <ext/date/php_date.h>
-}
+U_CDECL_END

 using icu::Calendar;

@@ -47,7 +47,7 @@ U_CDECL_END
 /* }}} */

 /* {{{ timezone_object_construct */
-U_CFUNC void timezone_object_construct(const TimeZone *zone, zval *object, int owned)
+void timezone_object_construct(const TimeZone *zone, zval *object, int owned)
 {
 	TimeZone_object	*to;

@@ -60,7 +60,7 @@ U_CFUNC void timezone_object_construct(const TimeZone *zone, zval *object, int o

 /* {{{ timezone_convert_to_datetimezone
  *	   Convert from TimeZone to DateTimeZone object */
-U_CFUNC zval *timezone_convert_to_datetimezone(const TimeZone *timeZone,
+zval *timezone_convert_to_datetimezone(const TimeZone *timeZone,
 											   intl_error *outside_error,
 											   zval *ret)
 {
@@ -120,7 +120,7 @@ static void timezone_throw_exception_with_call_location(const char *msg, const c

 /* {{{ timezone_process_timezone_argument
  * TimeZone argument processor. outside_error may be nullptr (for static functions/constructors) */
-U_CFUNC TimeZone *timezone_process_timezone_argument(
+TimeZone *timezone_process_timezone_argument(
 	zend_object *timezone_object, zend_string *timezone_string, intl_error *outside_error, uint32_t arg_num)
 {
 	std::unique_ptr<TimeZone>	timeZone;
@@ -349,7 +349,7 @@ static zend_object *TimeZone_object_create(zend_class_entry *ce)
 /* {{{ timezone_register_IntlTimeZone_class
  * Initialize 'IntlTimeZone' class
  */
-U_CFUNC void timezone_register_IntlTimeZone_class(void)
+void timezone_register_IntlTimeZone_class()
 {
 	/* Create and register 'IntlTimeZone' class. */
 	TimeZone_ce_ptr = register_class_IntlTimeZone();
diff --git a/ext/intl/timezone/timezone_class.h b/ext/intl/timezone/timezone_class.h
index cb74709c965..a864d7888f7 100644
--- a/ext/intl/timezone/timezone_class.h
+++ b/ext/intl/timezone/timezone_class.h
@@ -69,9 +69,11 @@ TimeZone *timezone_process_timezone_argument(zend_object *timezone_object, zend_

 void timezone_object_construct(const TimeZone *zone, zval *object, int owned);

+BEGIN_EXTERN_C()
 void timezone_register_IntlTimeZone_class(void);

 extern zend_class_entry *TimeZone_ce_ptr;
 extern zend_object_handlers TimeZone_handlers;
+END_EXTERN_C()

 #endif /* #ifndef TIMEZONE_CLASS_H */
diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp
index 118b153cc79..89d725217b9 100644
--- a/ext/intl/timezone/timezone_methods.cpp
+++ b/ext/intl/timezone/timezone_methods.cpp
@@ -26,14 +26,14 @@

 #include "../common/common_date.h"

-extern "C" {
 #include "../php_intl.h"
 #define USE_TIMEZONE_POINTER 1
 #include "timezone_class.h"
 #include "intl_convert.h"
 #include <zend_exceptions.h>
+BEGIN_EXTERN_C()
 #include <ext/date/php_date.h>
-}
+END_EXTERN_C()
 #include "common/common_enum.h"

 using icu::Locale;
diff --git a/ext/intl/transliterator/transliterator_class.cpp b/ext/intl/transliterator/transliterator_class.cpp
index 737c51fcf4d..c805b683510 100644
--- a/ext/intl/transliterator/transliterator_class.cpp
+++ b/ext/intl/transliterator/transliterator_class.cpp
@@ -13,13 +13,14 @@
  */

 #include "transliterator_class.h"
-extern "C" {
 #include "php_intl.h"
 #include "intl_error.h"
 #include "intl_convert.h"
 #include "intl_data.h"
+
+BEGIN_EXTERN_C()
 #include "transliterator_arginfo.h"
-}
+END_EXTERN_C()

 #include <unicode/utrans.h>

@@ -30,7 +31,7 @@ zend_object_handlers Transliterator_handlers;
 /* {{{ int transliterator_object_construct( zval *object, UTransliterator *utrans, UErrorCode *status )
  * Initialize internals of Transliterator_object.
  */
-U_CFUNC int transliterator_object_construct( zval *object,
+int transliterator_object_construct( zval *object,
 									 UTransliterator *utrans,
 									 UErrorCode *status )
 {
diff --git a/ext/intl/transliterator/transliterator_class.h b/ext/intl/transliterator/transliterator_class.h
index 1bdcd60eadc..83d5d2a895f 100644
--- a/ext/intl/transliterator/transliterator_class.h
+++ b/ext/intl/transliterator/transliterator_class.h
@@ -17,14 +17,8 @@

 #include <php.h>

-#ifdef __cplusplus
-extern "C" {
-#endif
 #include "intl_common.h"
 #include "intl_error.h"
-#ifdef __cplusplus
-}
-#endif

 #include <unicode/utrans.h>

@@ -60,19 +54,15 @@ typedef struct {
 		RETURN_THROWS(); \
 	}

-#ifdef __cplusplus
-extern "C" {
-#endif
 int transliterator_object_construct( zval *object,
 									 UTransliterator *utrans,
 									 UErrorCode *status );

+BEGIN_EXTERN_C()
 void transliterator_register_Transliterator_class( void );

 extern zend_class_entry *Transliterator_ce_ptr;
 extern zend_object_handlers Transliterator_handlers;
-#ifdef __cplusplus
-}
-#endif
+END_EXTERN_C()

 #endif /* #ifndef TRANSLITERATOR_CLASS_H */
diff --git a/ext/intl/transliterator/transliterator_methods.cpp b/ext/intl/transliterator/transliterator_methods.cpp
index db92be76824..64f9a2a0627 100644
--- a/ext/intl/transliterator/transliterator_methods.cpp
+++ b/ext/intl/transliterator/transliterator_methods.cpp
@@ -25,11 +25,9 @@
 #include <unicode/translit.h>
 #include "../intl_convertcpp.h"

-extern "C" {
 #include "php_intl.h"
 #include "intl_data.h"
 #include "intl_convert.h"
-}
 #include "transliterator.h"
 #include "transliterator_class.h"

diff --git a/ext/intl/uchar/uchar.cpp b/ext/intl/uchar/uchar.cpp
index b2df5b9a05a..3b3edfca49a 100644
--- a/ext/intl/uchar/uchar.cpp
+++ b/ext/intl/uchar/uchar.cpp
@@ -12,7 +12,6 @@
    +----------------------------------------------------------------------+
  */

-extern "C" {
 #include "uchar.h"
 #include "intl_data.h"
 #include "intl_convert.h"
@@ -21,7 +20,6 @@ extern "C" {
 #include <unicode/utf8.h>

 #include "uchar_arginfo.h"
-}

 #define IC_METHOD(mname) \
 static void php_intl_IntlChar_##mname##_impl(INTERNAL_FUNCTION_PARAMETERS); \
@@ -651,7 +649,7 @@ IC_CHAR_METHOD_CHAR(getBidiPairedBracket)
 #undef IC_CHAR_METHOD_CHAR
 /* }}} */

-int php_uchar_minit(INIT_FUNC_ARGS) {
+U_CFUNC int php_uchar_minit(INIT_FUNC_ARGS) {
 	register_class_IntlChar();

 	return SUCCESS;
diff --git a/ext/intl/uchar/uchar.h b/ext/intl/uchar/uchar.h
index 7b472163ab0..4ec50b700d7 100644
--- a/ext/intl/uchar/uchar.h
+++ b/ext/intl/uchar/uchar.h
@@ -17,6 +17,8 @@

 #include "php.h"

+BEGIN_EXTERN_C()
 int php_uchar_minit(INIT_FUNC_ARGS);
+END_EXTERN_C()

 #endif // incl_PHP_INTL_UCHAR_H