--- include/ffi.h.in
+++ include/ffi.h.in
@@ -66,6 +66,18 @@
 
 #include <ffitarget.h>
 
+#if defined _MSC_VER
+#  if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */
+#    define FFI_EXTERN __declspec(dllexport)
+#  elif !defined FFI_BUILDING /* Importing libffi.DLL */
+#    define FFI_EXTERN __declspec(dllimport)
+#  else
+#    define FFI_EXTERN extern
+#  endif
+#else
+#  define FFI_EXTERN extern
+#endif
+
 #ifndef LIBFFI_ASM
 
 #if defined(_MSC_VER) && !defined(__clang__)
@@ -166,20 +180,6 @@
  #error "long size not supported"
 #endif
 
-/* Need minimal decorations for DLLs to works on Windows. */
-/* GCC has autoimport and autoexport.  Rely on Libtool to */
-/* help MSVC export from a DLL, but always declare data   */
-/* to be imported for MSVC clients.  This costs an extra  */
-/* indirection for MSVC clients using the static version  */
-/* of the library, but don't worry about that.  Besides,  */
-/* as a workaround, they can define FFI_BUILDING if they  */
-/* *know* they are going to link with the static library. */
-#if defined _MSC_VER && !defined FFI_BUILDING
-#define FFI_EXTERN extern __declspec(dllimport)
-#else
-#define FFI_EXTERN extern
-#endif
-
 /* These are defined in types.c */
 FFI_EXTERN ffi_type ffi_type_void;
 FFI_EXTERN ffi_type ffi_type_uint8;
@@ -237,7 +237,7 @@
 #endif
 
 /* Used internally, but overridden by some architectures */
-ffi_status ffi_prep_cif_core(ffi_cif *cif,
+FFI_EXTERN ffi_status ffi_prep_cif_core(ffi_cif *cif,
 			     ffi_abi abi,
 			     unsigned int isvariadic,
 			     unsigned int nfixedargs,
@@ -282,27 +282,27 @@
 #endif
 
 
-void ffi_raw_call (ffi_cif *cif,
+FFI_EXTERN void ffi_raw_call (ffi_cif *cif,
 		   void (*fn)(void),
 		   void *rvalue,
 		   ffi_raw *avalue);
 
-void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-size_t ffi_raw_size (ffi_cif *cif);
+FFI_EXTERN void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+FFI_EXTERN void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
+FFI_EXTERN size_t ffi_raw_size (ffi_cif *cif);
 
 /* This is analogous to the raw API, except it uses Java parameter	*/
 /* packing, even on 64-bit machines.  I.e. on 64-bit machines		*/
 /* longs and doubles are followed by an empty 64-bit word.		*/
 
-void ffi_java_raw_call (ffi_cif *cif,
+FFI_EXTERN void ffi_java_raw_call (ffi_cif *cif,
 			void (*fn)(void),
 			void *rvalue,
 			ffi_java_raw *avalue);
 
-void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
-void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
-size_t ffi_java_raw_size (ffi_cif *cif);
+FFI_EXTERN void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
+FFI_EXTERN void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
+FFI_EXTERN size_t ffi_java_raw_size (ffi_cif *cif);
 
 /* ---- Definitions for closures ----------------------------------------- */
 
@@ -330,16 +330,16 @@
 # endif
 #endif
 
-void *ffi_closure_alloc (size_t size, void **code);
-void ffi_closure_free (void *);
+FFI_EXTERN void *ffi_closure_alloc (size_t size, void **code);
+FFI_EXTERN void ffi_closure_free (void *);
 
-ffi_status
+FFI_EXTERN ffi_status
 ffi_prep_closure (ffi_closure*,
 		  ffi_cif *,
 		  void (*fun)(ffi_cif*,void*,void**,void*),
 		  void *user_data);
 
-ffi_status
+FFI_EXTERN ffi_status
 ffi_prep_closure_loc (ffi_closure*,
 		      ffi_cif *,
 		      void (*fun)(ffi_cif*,void*,void**,void*),
@@ -400,26 +400,26 @@
 
 } ffi_java_raw_closure;
 
-ffi_status
+FFI_EXTERN ffi_status
 ffi_prep_raw_closure (ffi_raw_closure*,
 		      ffi_cif *cif,
 		      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
 		      void *user_data);
 
-ffi_status
+FFI_EXTERN ffi_status
 ffi_prep_raw_closure_loc (ffi_raw_closure*,
 			  ffi_cif *cif,
 			  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
 			  void *user_data,
 			  void *codeloc);
 
-ffi_status
+FFI_EXTERN ffi_status
 ffi_prep_java_raw_closure (ffi_java_raw_closure*,
 		           ffi_cif *cif,
 		           void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
 		           void *user_data);
 
-ffi_status
+FFI_EXTERN ffi_status
 ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
 			       ffi_cif *cif,
 			       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
@@ -430,20 +430,20 @@
 
 /* ---- Public interface definition -------------------------------------- */
 
-ffi_status ffi_prep_cif(ffi_cif *cif,
+FFI_EXTERN ffi_status ffi_prep_cif(ffi_cif *cif,
 			ffi_abi abi,
 			unsigned int nargs,
 			ffi_type *rtype,
 			ffi_type **atypes);
 
-ffi_status ffi_prep_cif_var(ffi_cif *cif,
+FFI_EXTERN ffi_status ffi_prep_cif_var(ffi_cif *cif,
 			    ffi_abi abi,
 			    unsigned int nfixedargs,
 			    unsigned int ntotalargs,
 			    ffi_type *rtype,
 			    ffi_type **atypes);
 
-void ffi_call(ffi_cif *cif,
+FFI_EXTERN void ffi_call(ffi_cif *cif,
 	      void (*fn)(void),
 	      void *rvalue,
 	      void **avalue);
