Bladeren bron

Merge pull request #295 from zhindes/master

Support default __stdcall calling convention (/Gz) on Windows
Max Bruckner 6 jaren geleden
bovenliggende
commit
3550a5553d

+ 2 - 0
.gitattributes

@@ -0,0 +1,2 @@
+*  					text=auto
+/tests/inputs/*	text eol=lf

+ 4 - 0
CMakeLists.txt

@@ -49,11 +49,15 @@ if (ENABLE_CUSTOM_COMPILER_FLAGS)
             -Wswitch-enum
         )
     elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
+        # Disable warning c4001 - nonstandard extension 'single line comment' was used
+        # Define _CRT_SECURE_NO_WARNINGS to disable deprecation warnings for "insecure" C library functions
         list(APPEND custom_compiler_flags
             /GS
             /Za
             /sdl
             /W4
+            /wd4001
+            /D_CRT_SECURE_NO_WARNINGS
         )
     endif()
 endif()

+ 6 - 6
cJSON.c

@@ -119,22 +119,22 @@ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned
 
 typedef struct internal_hooks
 {
-    void *(*allocate)(size_t size);
-    void (*deallocate)(void *pointer);
-    void *(*reallocate)(void *pointer, size_t size);
+    void *(CJSON_CDECL *allocate)(size_t size);
+    void (CJSON_CDECL *deallocate)(void *pointer);
+    void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
 } internal_hooks;
 
 #if defined(_MSC_VER)
 /* work around MSVC error C2322: '...' address of dillimport '...' is not static */
-static void *internal_malloc(size_t size)
+static void * CJSON_CDECL internal_malloc(size_t size)
 {
     return malloc(size);
 }
-static void internal_free(void *pointer)
+static void CJSON_CDECL internal_free(void *pointer)
 {
     free(pointer);
 }
-static void *internal_realloc(void *pointer, size_t size)
+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
 {
     return realloc(pointer, size);
 }

+ 53 - 45
cJSON.h

@@ -28,6 +28,56 @@ extern "C"
 {
 #endif
 
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+
+#ifdef __WINDOWS__
+
+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 3 define options:
+
+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+
+For *nix builds that support visibility attribute, you can define similar behavior by
+
+setting default visibility to hidden by adding
+-fvisibility=hidden (for gcc)
+or
+-xldscope=hidden (for sun cc)
+to CFLAGS
+
+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+
+*/
+
+#define CJSON_CDECL __cdecl
+#define CJSON_STDCALL __stdcall
+
+/* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type)   type CJSON_STDCALL
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type)   __declspec(dllexport) type CJSON_STDCALL
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type)   __declspec(dllimport) type CJSON_STDCALL
+#endif
+#else /* !__WINDOWS__ */
+#define CJSON_CDECL
+#define CJSON_STDCALL
+
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type)   __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
 /* project version */
 #define CJSON_VERSION_MAJOR 1
 #define CJSON_VERSION_MINOR 7
@@ -74,55 +124,13 @@ typedef struct cJSON
 
 typedef struct cJSON_Hooks
 {
-      void *(*malloc_fn)(size_t sz);
-      void (*free_fn)(void *ptr);
+      /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
+      void *(CJSON_CDECL *malloc_fn)(size_t sz);
+      void (CJSON_CDECL *free_fn)(void *ptr);
 } cJSON_Hooks;
 
 typedef int cJSON_bool;
 
-#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
-#define __WINDOWS__
-#endif
-#ifdef __WINDOWS__
-
-/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 2 define options:
-
-CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
-CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
-CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
-
-For *nix builds that support visibility attribute, you can define similar behavior by
-
-setting default visibility to hidden by adding
--fvisibility=hidden (for gcc)
-or
--xldscope=hidden (for sun cc)
-to CFLAGS
-
-then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
-
-*/
-
-/* export symbols by default, this is necessary for copy pasting the C and header file */
-#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
-#define CJSON_EXPORT_SYMBOLS
-#endif
-
-#if defined(CJSON_HIDE_SYMBOLS)
-#define CJSON_PUBLIC(type)   type __stdcall
-#elif defined(CJSON_EXPORT_SYMBOLS)
-#define CJSON_PUBLIC(type)   __declspec(dllexport) type __stdcall
-#elif defined(CJSON_IMPORT_SYMBOLS)
-#define CJSON_PUBLIC(type)   __declspec(dllimport) type __stdcall
-#endif
-#else /* !WIN32 */
-#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
-#define CJSON_PUBLIC(type)   __attribute__((visibility("default"))) type
-#else
-#define CJSON_PUBLIC(type) type
-#endif
-#endif
-
 /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
  * This is to prevent stack overflows. */
 #ifndef CJSON_NESTING_LIMIT

+ 1 - 1
test.c

@@ -256,7 +256,7 @@ static void create_objects(void)
     cJSON_Delete(root);
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* print the version */
     printf("Version: %s\n", cJSON_Version());

+ 4 - 1
tests/CMakeLists.txt

@@ -1,5 +1,5 @@
 if(ENABLE_CJSON_TEST)
-    add_library(unity "${CJSON_LIBRARY_TYPE}" unity/src/unity.c)
+    add_library(unity STATIC unity/src/unity.c)
 
     # Disable -Werror for Unity
     if (FLAG_SUPPORTED_Werror)
@@ -72,6 +72,9 @@ if(ENABLE_CJSON_TEST)
 
     foreach(unity_test ${unity_tests})
         add_executable("${unity_test}" "${unity_test}.c")
+        if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
+            target_sources(${unity_test} PRIVATE unity_setup.c)
+        endif()
         target_link_libraries("${unity_test}" "${CJSON_LIB}" unity)
         if(MEMORYCHECK_COMMAND)
             add_test(NAME "${unity_test}"

+ 9 - 3
tests/cjson_add.c

@@ -28,15 +28,21 @@
 #include "unity/src/unity.h"
 #include "common.h"
 
-static void *failing_malloc(size_t size)
+static void * CJSON_CDECL failing_malloc(size_t size)
 {
     (void)size;
     return NULL;
 }
 
+/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
+static void CJSON_CDECL normal_free(void *pointer)
+{
+    free(pointer);
+}
+
 static cJSON_Hooks failing_hooks = {
     failing_malloc,
-    free
+    normal_free
 };
 
 static void cjson_add_null_should_add_null(void)
@@ -372,7 +378,7 @@ static void cjson_add_array_should_fail_on_allocation_failure(void)
     cJSON_Delete(root);
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     UNITY_BEGIN();
 

+ 1 - 1
tests/compare_tests.c

@@ -186,7 +186,7 @@ static void cjson_compare_should_compare_objects(void)
                 false))
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     UNITY_BEGIN();
 

+ 2 - 2
tests/misc_tests.c

@@ -410,7 +410,7 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
     cJSON_Delete(item);
 }
 
-static void *failing_realloc(void *pointer, size_t size)
+static void * CJSON_CDECL failing_realloc(void *pointer, size_t size)
 {
     (void)size;
     (void)pointer;
@@ -527,7 +527,7 @@ static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_al
     cJSON_Delete(object);
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     UNITY_BEGIN();
 

+ 1 - 1
tests/parse_array.c

@@ -152,7 +152,7 @@ static void parse_array_should_not_parse_non_arrays(void)
     assert_not_array("\"[]hello world!\n\"");
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     memset(item, 0, sizeof(cJSON));

+ 1 - 1
tests/parse_examples.c

@@ -195,7 +195,7 @@ static void test12_should_not_be_parsed(void)
     }
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     UNITY_BEGIN();
     RUN_TEST(file_test1_should_be_parsed_and_printed);

+ 1 - 1
tests/parse_hex4.c

@@ -64,7 +64,7 @@ static void parse_hex4_should_parse_mixed_case(void)
     TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEEF"));
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     UNITY_BEGIN();
     RUN_TEST(parse_hex4_should_parse_all_combinations);

+ 1 - 1
tests/parse_number.c

@@ -96,7 +96,7 @@ static void parse_number_should_parse_negative_reals(void)
     assert_parse_number("-123e-128", 0, -123e-128);
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     memset(item, 0, sizeof(cJSON));

+ 1 - 1
tests/parse_object.c

@@ -162,7 +162,7 @@ static void parse_object_should_not_parse_non_objects(void)
     assert_not_object("\"{}hello world!\n\"");
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     memset(item, 0, sizeof(cJSON));

+ 1 - 1
tests/parse_string.c

@@ -119,7 +119,7 @@ static void parse_string_should_parse_bug_94(void)
     reset(item);
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item and error pointer */
     memset(item, 0, sizeof(cJSON));

+ 1 - 1
tests/parse_value.c

@@ -96,7 +96,7 @@ static void parse_value_should_parse_object(void)
     reset(item);
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     memset(item, 0, sizeof(cJSON));

+ 1 - 1
tests/parse_with_opts.c

@@ -97,7 +97,7 @@ static void parse_with_opts_should_parse_utf8_bom(void)
     cJSON_Delete(without_bom);
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     UNITY_BEGIN();
 

+ 1 - 1
tests/print_array.c

@@ -87,7 +87,7 @@ static void print_array_should_print_arrays_with_multiple_elements(void)
     assert_print_array("[1, null, true, false, [], \"hello\", {\n\t}]", "[1,null,true,false,[],\"hello\",{}]");
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     UNITY_BEGIN();

+ 1 - 1
tests/print_number.c

@@ -89,7 +89,7 @@ static void print_number_should_print_non_number(void)
     /* assert_print_number("null", -INFTY); */
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     UNITY_BEGIN();

+ 1 - 1
tests/print_object.c

@@ -88,7 +88,7 @@ static void print_object_should_print_objects_with_multiple_elements(void)
     assert_print_object("{\n\t\"one\":\t1,\n\t\"NULL\":\tnull,\n\t\"TRUE\":\ttrue,\n\t\"FALSE\":\tfalse,\n\t\"array\":\t[],\n\t\"world\":\t\"hello\",\n\t\"object\":\t{\n\t}\n}", "{\"one\":1,\"NULL\":null,\"TRUE\":true,\"FALSE\":false,\"array\":[],\"world\":\"hello\",\"object\":{}}");
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     UNITY_BEGIN();

+ 1 - 1
tests/print_string.c

@@ -65,7 +65,7 @@ static void print_string_should_print_utf8(void)
     assert_print_string("\"ü猫慕\"", "ü猫慕");
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     UNITY_BEGIN();

+ 1 - 1
tests/print_value.c

@@ -90,7 +90,7 @@ static void print_value_should_print_object(void)
     assert_print_value("{}");
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     /* initialize cJSON item */
     UNITY_BEGIN();

+ 1 - 1
tests/readme_examples.c

@@ -246,7 +246,7 @@ static void supports_full_hd_should_check_for_full_hd_support(void)
     TEST_ASSERT_FALSE(supports_full_hd(monitor_without_hd));
 }
 
-int main(void)
+int CJSON_CDECL main(void)
 {
     UNITY_BEGIN();
 

+ 3 - 0
tests/unity_setup.c

@@ -0,0 +1,3 @@
+// msvc doesn't support weak-linking, so we need to define these functions.
+void setUp(void) { }
+void tearDown(void) { }