diff --git a/CMakeLists.txt b/CMakeLists.txt index 34c8755fd..ddd2fd260 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,6 +172,7 @@ target_compile_features(libhl PUBLIC cxx_std_11 c_std_11) set(public_headers src/hl.h + src/hl_ffi.h src/hlc.h ) diff --git a/Makefile b/Makefile index 004bbfc79..821f223f2 100644 --- a/Makefile +++ b/Makefile @@ -257,11 +257,11 @@ endif cp *.hdll $(INSTALL_LIB_DIR) cp $(LIBHL) $(INSTALL_LIB_DIR) mkdir -p $(INSTALL_INCLUDE_DIR) - cp src/hl.h src/hlc.h src/hlc_main.c $(INSTALL_INCLUDE_DIR) + cp src/hl.h src/hl_ffi.h src/hlc.h src/hlc_main.c $(INSTALL_INCLUDE_DIR) uninstall: rm -f $(INSTALL_BIN_DIR)/$(HL) $(INSTALL_LIB_DIR)/$(LIBHL) $(INSTALL_LIB_DIR)/*.hdll - rm -f $(INSTALL_INCLUDE_DIR)/hl.h $(INSTALL_INCLUDE_DIR)/hlc.h $(INSTALL_INCLUDE_DIR)/hlc_main.c + rm -f $(INSTALL_INCLUDE_DIR)/hl.h $(INSTALL_INCLUDE_DIR)/hl_ffi.h $(INSTALL_INCLUDE_DIR)/hlc.h $(INSTALL_INCLUDE_DIR)/hlc_main.c libs: $(LIBS) @@ -350,7 +350,7 @@ release_prepare: rm -rf $(PACKAGE_NAME) mkdir $(PACKAGE_NAME) mkdir $(PACKAGE_NAME)/include - cp src/hl.h src/hlc.h src/hlc_main.c $(PACKAGE_NAME)/include + cp src/hl.h src/hl_ffi.h src/hlc.h src/hlc_main.c $(PACKAGE_NAME)/include release_win: cp $(BUILD_DIR)/{$(HL),libhl.dll,*.hdll,*.lib} $(PACKAGE_NAME) diff --git a/src/hl.h b/src/hl.h index d75b98fe9..a7d633199 100644 --- a/src/hl.h +++ b/src/hl.h @@ -165,16 +165,20 @@ #include #include -#if defined(HL_VCC) || defined(HL_MINGW) -# define EXPORT __declspec( dllexport ) -# define IMPORT __declspec( dllimport ) -#else -#if defined(HL_GCC) || defined(HL_CLANG) -# define EXPORT __attribute__((visibility("default"))) -#else -# define EXPORT +#ifndef HL_EXPORT +# ifdef HL_WIN +# define HL_EXPORT __declspec( dllexport ) +# elif defined(HL_GCC) || defined(HL_CLANG) +# define HL_EXPORT __attribute__((visibility("default"))) +# else +# define HL_EXPORT +# endif #endif -# define IMPORT extern + +#ifdef HL_WIN +# define HL_IMPORT __declspec( dllimport ) +#else +# define HL_IMPORT extern #endif #ifdef HL_64 @@ -196,9 +200,15 @@ #endif #ifdef __cplusplus -# define C_FUNCTION_BEGIN extern "C" { +# ifndef HL_EXTERN_C +# define HL_EXTERN_C extern "C" +# endif +# define C_FUNCTION_BEGIN HL_EXTERN_C { # define C_FUNCTION_END }; #else +# ifndef HL_EXTERN_C +# define HL_EXTERN_C +# endif # define C_FUNCTION_BEGIN # define C_FUNCTION_END #endif @@ -213,11 +223,11 @@ typedef unsigned long long uint64; #include #if defined(LIBHL_EXPORTS) -#define HL_API extern EXPORT +#define HL_API extern HL_EXPORT #elif defined(LIBHL_STATIC) #define HL_API extern #else -#define HL_API IMPORT +#define HL_API HL_IMPORT #endif #if defined(HL_VCC) @@ -845,6 +855,16 @@ HL_API void hl_throw_buffer( hl_buffer *b ); // ----------------------- FFI ------------------------------------------------------ +#ifndef HL_DISABLE_LEGACY_FFI + +#if defined(HLFFI_H) +# if defined(_MSC_VER) +# pragma message("Warning: Please define HL_DISABLE_LEGACY_FFI if using hl.h with hl_ffi.h") +# else +# warning Please define HL_DISABLE_LEGACY_FFI if using hl.h with hl_ffi.h +# endif +#endif + // match GNU C++ mangling #define TYPE_STR "vcsilfdbBDPOATR??X?N?S?g" @@ -874,42 +894,39 @@ HL_API void hl_throw_buffer( hl_buffer *b ); #undef _STRING #define _STRING _OBJ(_BYTES _I32) -typedef struct { - hl_type *t; - uchar *bytes; - int length; -} vstring; - -#define DEFINE_PRIM(t,name,args) DEFINE_PRIM_WITH_NAME(t,name,args,name) -#define _DEFINE_PRIM_WITH_NAME(t,name,args,realName) C_FUNCTION_BEGIN EXPORT void *hlp_##realName( const char **sign ) { *sign = _FUN(t,args); return (void*)(&HL_NAME(name)); } C_FUNCTION_END +#if defined(LIBHL_EXPORTS) +# define DEFINE_PRIM(t,name,args) DEFINE_PRIM_WITH_NAME(t,hl_##name,args,name) +#else +# define DEFINE_PRIM(t,name,args) DEFINE_PRIM_WITH_NAME(t,name,args,name) +#endif -#if !defined(HL_NAME) -# define HL_NAME(p) p -# ifdef LIBHL_EXPORTS -# define HL_PRIM EXPORT -# undef DEFINE_PRIM -# define DEFINE_PRIM(t,name,args) _DEFINE_PRIM_WITH_NAME(t,hl_##name,args,name) -# define DEFINE_PRIM_WITH_NAME _DEFINE_PRIM_WITH_NAME -# else -# define HL_PRIM -# define DEFINE_PRIM_WITH_NAME(t,name,args,realName) -# endif -#elif defined(LIBHL_STATIC) -# ifdef __cplusplus -# define HL_PRIM extern "C" -# else -# define HL_PRIM +#if (defined(HL_NAME) && !defined(LIBHL_STATIC)) || defined(LIBHL_EXPORTS) +# ifndef HL_PRIM +# define HL_PRIM HL_EXTERN_C HL_EXPORT # endif -#define DEFINE_PRIM_WITH_NAME(t,name,args,realName) +# define DEFINE_PRIM_WITH_NAME(t,name,args,realName) HL_EXTERN_C HL_EXPORT void *hlp_##realName( const char **sign ) { *sign = _FUN(t,args); return (void*)(&HL_NAME(name)); } #else -# ifdef __cplusplus -# define HL_PRIM extern "C" EXPORT -# else -# define HL_PRIM EXPORT +# ifndef HL_PRIM +# define HL_PRIM HL_EXTERN_C # endif -# define DEFINE_PRIM_WITH_NAME _DEFINE_PRIM_WITH_NAME +# define DEFINE_PRIM_WITH_NAME(t,name,args,realName) +#endif + +#ifndef HL_NAME +# define HL_NAME(p) p #endif +#define EXPORT HL_EXPORT +#define IMPORT HL_IMPORT + +#endif // HL_DISABLE_LEGACY_FFI + +typedef struct { + hl_type *t; + uchar *bytes; + int length; +} vstring; + #if defined(HL_GCC) && !defined(HL_CONSOLE) # ifdef HL_CLANG # define HL_NO_OPT __attribute__ ((optnone)) @@ -1022,4 +1039,9 @@ HL_API hl_track_info hl_track; C_FUNCTION_END +#ifndef HL_DISABLE_LEGACY_FFI +# undef C_FUNCTION_BEGIN +# undef C_FUNCTION_END +#endif + #endif diff --git a/src/hl_ffi.h b/src/hl_ffi.h new file mode 100644 index 000000000..4af06187b --- /dev/null +++ b/src/hl_ffi.h @@ -0,0 +1,66 @@ +#ifndef HLFFI_H +#define HLFFI_H + +#if defined(HL_H) && !defined(HL_DISABLE_LEGACY_FFI) +# if defined(_MSC_VER) +# pragma message("Warning: Please define HL_DISABLE_LEGACY_FFI if using hl.h before hl_ffi.h") +# else +# warning Please define HL_DISABLE_LEGACY_FFI if using hl.h before hl_ffi.h +# endif +#endif + +// match GNU C++ mangling +#define HL_TYPE_STR "vcsilfdbBDPOATR??X?N?S?g" + +#define HL_NO_ARG +#define HL_VOID "v" +#define HL_I8 "c" +#define HL_I16 "s" +#define HL_I32 "i" +#define HL_I64 "l" +#define HL_F32 "f" +#define HL_F64 "d" +#define HL_BOOL "b" +#define HL_BYTES "B" +#define HL_DYN "D" +#define HL_FUN(t, args) "P" args "_" t +#define HL_OBJ(fields) "O" fields "_" +#define HL_ARR "A" +#define HL_TYPE "T" +#define HL_REF(t) "R" t +#define HL_ABSTRACT(name) "X" #name "_" +#define HL_NULL(t) "N" t +#define HL_STRUCT "S" +#define HL_GUID "g" + +#define HL_STRING HL_OBJ(HL_BYTES HL_I32) + +#ifndef HL_EXTERN_C +# ifdef __cplusplus +# define HL_EXTERN_C extern "C" +# else +# define HL_EXTERN_C +# endif +#endif + +#ifndef HL_EXPORT +# if defined(_WIN32) +# define HL_EXPORT __declspec( dllexport ) +# elif defined(__GNUC__) || defined(__clang__) +# define HL_EXPORT __attribute__((visibility("default"))) +# else +# define HL_EXPORT +# endif +#endif + +#define HL_DEFINE_PRIM(t,name,args) HL_DEFINE_PRIM_WITH_NAME(t,name,args,name) + +#ifdef HL_NAME +# define HL_PRIM HL_EXTERN_C HL_EXPORT +# define HL_DEFINE_PRIM_WITH_NAME(t,name,args,realName) HL_EXTERN_C HL_EXPORT void *hlp_##realName( const char **sign ) { *sign = HL_FUN(t,args); return (void*)(&HL_NAME(name)); } +#else +# define HL_PRIM HL_EXTERN_C +# define HL_DEFINE_PRIM_WITH_NAME(t,name,args,realName) +#endif + +#endif // ifndef HLFFI_H diff --git a/src/hlc.h b/src/hlc.h index c8ca0e405..7def07dee 100644 --- a/src/hlc.h +++ b/src/hlc.h @@ -23,6 +23,7 @@ #define HLC_H #include +#define HL_DISABLE_LEGACY_FFI #include #ifdef HLC_BOOT