forked from LeenkxTeam/LNXSDK
		
	
		
			
				
	
	
		
			331 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			331 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef HX_CFFI_LOADER_H
 | 
						|
#define HX_CFFI_LOADER_H
 | 
						|
 | 
						|
/*
 | 
						|
  This file will only be incuded in one cpp file in the ndll library -
 | 
						|
    the one with IMPLEMENT_API #defined.
 | 
						|
 | 
						|
  The other files will refer to the val_ functions via the "extern" in CFFI.h
 | 
						|
 | 
						|
  For dynamic linking, a macro (DEFFUNC) implements the "val_..." functions as function pointers,
 | 
						|
   and the cpp code calls these function pointers directly.
 | 
						|
  The pointers starts off as function pointers to bootstrap code, so when they are first called
 | 
						|
   the bootstrap uses the "ResolveProc" to find the correct version of the function for the particular
 | 
						|
   platform, and replaces the function pointer with this value. Subsequent calls then go directly
 | 
						|
   to the correct fucntion.
 | 
						|
 | 
						|
  The ResolveProc can come from:
 | 
						|
   Explicitly setting - the proc is set when a dll is loaded into the hxcpp exe
 | 
						|
   Via 'GetProcAddress' on the exe - if symbols are needed and the proc has not been set
 | 
						|
   Internal implementation (CFFINekoLoader) - when linking agaist a neko process.
 | 
						|
    - Old code used to find this in NekoApi.dll, but the glue code is now built into each ndll directly.
 | 
						|
 | 
						|
  For static linking, the functions are resolved at link time.
 | 
						|
 | 
						|
  For HXCPP_JS_PRIME, these functions are implemented in CFFIJsPrime
 | 
						|
*/
 | 
						|
 | 
						|
#ifdef ANDROID
 | 
						|
#include <android/log.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef NEKO_WINDOWS
 | 
						|
#include <windows.h>
 | 
						|
#include <stdio.h>
 | 
						|
// Stoopid windows ...
 | 
						|
#ifdef RegisterClass
 | 
						|
#undef RegisterClass
 | 
						|
#endif
 | 
						|
#ifdef abs
 | 
						|
#undef abs
 | 
						|
#endif
 | 
						|
 | 
						|
#else // NOT NEKO_WINDOWS
 | 
						|
 | 
						|
#ifdef NEKO_LINUX
 | 
						|
#define EXT "dso"
 | 
						|
#define NEKO_EXT "so"
 | 
						|
//#define __USE_GNU 1
 | 
						|
 | 
						|
#elif defined(HX_MACOS)
 | 
						|
#include <mach-o/dyld.h>
 | 
						|
#define EXT "dylib"
 | 
						|
#define NEKO_EXT "dylib"
 | 
						|
 | 
						|
#else
 | 
						|
#if defined(EMSCRIPTEN)
 | 
						|
#define EXT "ll"
 | 
						|
#else
 | 
						|
#define EXT "so"
 | 
						|
#endif
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
#include <dlfcn.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <memory.h>
 | 
						|
 | 
						|
 | 
						|
#endif
 | 
						|
#if defined(BLACKBERRY)
 | 
						|
using namespace std;
 | 
						|
#endif
 | 
						|
typedef void *(*ResolveProc)(const char *inName);
 | 
						|
static ResolveProc sResolveProc = 0;
 | 
						|
 | 
						|
extern "C" {
 | 
						|
EXPORT void hx_set_loader(ResolveProc inProc)
 | 
						|
{
 | 
						|
   #ifdef ANDROID
 | 
						|
   __android_log_print(ANDROID_LOG_INFO, "haxe plugin", "Got Load Proc %p", inProc );
 | 
						|
   #endif
 | 
						|
   sResolveProc = inProc;
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#ifdef HXCPP_JS_PRIME // { js prime
 | 
						|
 | 
						|
#define DEFFUNC(name,ret,def_args,call_args) \
 | 
						|
extern "C" ret name def_args;
 | 
						|
 | 
						|
#include "CFFIJsPrime.h"
 | 
						|
 | 
						|
#elif defined(STATIC_LINK)  // js prime }   { not js prime, static link
 | 
						|
 | 
						|
#define DEFFUNC(name,ret,def_args,call_args) \
 | 
						|
extern "C" ret name def_args;
 | 
						|
 | 
						|
#else  // static link }   { Dynamic link
 | 
						|
 | 
						|
   #ifdef NEKO_COMPATIBLE
 | 
						|
 | 
						|
      #include "CFFINekoLoader.h"
 | 
						|
 | 
						|
   #endif // NEKO_COMPATIBLE
 | 
						|
 | 
						|
 | 
						|
   // This code will get run when the library is compiled against a newer version of hxcpp,
 | 
						|
   //  and the application code uses an older version.
 | 
						|
   bool default_val_is_buffer(void *inBuffer)
 | 
						|
   {
 | 
						|
      typedef void *(ValToBufferFunc)(void *);
 | 
						|
      static ValToBufferFunc *valToBuffer = 0;
 | 
						|
      if (!valToBuffer)
 | 
						|
         valToBuffer = (ValToBufferFunc *)sResolveProc("val_to_buffer");
 | 
						|
 | 
						|
      if (valToBuffer)
 | 
						|
         return valToBuffer(inBuffer)!=0;
 | 
						|
 | 
						|
      return false;
 | 
						|
   }
 | 
						|
 | 
						|
   // Neko, old cpp and js_prime are all utf8 based - and go through here
 | 
						|
   #ifdef HXCPP_PRIME
 | 
						|
   struct DynAlloc : public hx::IStringAlloc
 | 
						|
   {
 | 
						|
      #define WANT_DYNALLOC_ALLOC_BYTES
 | 
						|
      void *allocBytes(size_t n);
 | 
						|
   };
 | 
						|
 | 
						|
 | 
						|
   HxString default_string_wchar(const wchar_t *src,int len)
 | 
						|
   {
 | 
						|
      hx::strbuf buf;
 | 
						|
      const char *str = cffi::to_utf8(src,len,&buf);
 | 
						|
      return HxString(str,len);
 | 
						|
   }
 | 
						|
   HxString default_string_utf8(const char *str,int len)
 | 
						|
   {
 | 
						|
      return HxString(str,len);
 | 
						|
   }
 | 
						|
   HxString default_string_utf16(const char16_t *src,int len)
 | 
						|
   {
 | 
						|
      hx::strbuf buf;
 | 
						|
      const char *str = cffi::to_utf8(src,len,&buf);
 | 
						|
      return HxString(str,len);
 | 
						|
   }
 | 
						|
 | 
						|
   const char *default_to_utf8(const HxString &str,hx::IStringAlloc *alloc)
 | 
						|
   {
 | 
						|
      return str.c_str();
 | 
						|
   }
 | 
						|
   const wchar_t *default_to_wchar(const HxString &str,hx::IStringAlloc *alloc)
 | 
						|
   {
 | 
						|
      DynAlloc d;
 | 
						|
      if (!alloc)
 | 
						|
         alloc = &d;
 | 
						|
      return cffi::from_utf8<wchar_t>(str.c_str(),str.size(),alloc);
 | 
						|
   }
 | 
						|
   const char16_t *default_to_utf16(const HxString &str,hx::IStringAlloc *alloc)
 | 
						|
   {
 | 
						|
      DynAlloc d;
 | 
						|
      if (!alloc)
 | 
						|
         alloc = &d;
 | 
						|
      return cffi::from_utf8<char16_t>(str.c_str(),str.size(),alloc);
 | 
						|
   }
 | 
						|
   #endif
 | 
						|
 | 
						|
 | 
						|
   hx::StringEncoding default_get_encoding(void *inPtr) { return hx::StringUtf8; }
 | 
						|
 | 
						|
   void * default_alloc_empty_string(int) { return 0; }
 | 
						|
 | 
						|
   // Do nothing on earlier versions of hxcpp that do not know what to do
 | 
						|
   void default_gc_change_managed_memory(int,const char *) { }
 | 
						|
 | 
						|
   void *ResolveDefault(const char *inName)
 | 
						|
   {
 | 
						|
      void *result = sResolveProc(inName);
 | 
						|
      if (result)
 | 
						|
         return result;
 | 
						|
      if (!strcmp(inName,"val_is_buffer"))
 | 
						|
         return (void *)default_val_is_buffer;
 | 
						|
      if (!strcmp(inName,"alloc_empty_string"))
 | 
						|
         return (void *)default_alloc_empty_string;
 | 
						|
      if (!strcmp(inName,"gc_change_managed_memory"))
 | 
						|
         return (void *)default_gc_change_managed_memory;
 | 
						|
      if (!strcmp(inName,"hxs_encoding"))
 | 
						|
         return (void *)default_get_encoding;
 | 
						|
      #ifdef HXCPP_PRIME
 | 
						|
      if (!strcmp(inName,"alloc_hxs_wchar"))
 | 
						|
         return (void *)default_string_wchar;
 | 
						|
      if (!strcmp(inName,"alloc_hxs_utf16"))
 | 
						|
         return (void *)default_string_utf16;
 | 
						|
      if (!strcmp(inName,"alloc_hxs_utf8"))
 | 
						|
         return (void *)default_string_utf8;
 | 
						|
      if (!strcmp(inName,"hxs_utf8"))
 | 
						|
         return (void *)default_to_utf8;
 | 
						|
      if (!strcmp(inName,"hxs_utf16"))
 | 
						|
         return (void *)default_to_utf16;
 | 
						|
      if (!strcmp(inName,"hxs_wchar"))
 | 
						|
         return (void *)default_to_wchar;
 | 
						|
      #endif
 | 
						|
 | 
						|
      return 0;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef NEKO_WINDOWS // {
 | 
						|
 | 
						|
   void *LoadFunc(const char *inName)
 | 
						|
   {
 | 
						|
      #ifndef HX_WINRT
 | 
						|
      static const char *modules[] = { 0, "hxcpp", "hxcpp-debug" };
 | 
						|
      for(int i=0; i<3 && sResolveProc==0; i++)
 | 
						|
      {
 | 
						|
         HMODULE handle = GetModuleHandleA(modules[i]);
 | 
						|
         if (handle)
 | 
						|
         {
 | 
						|
            sResolveProc = (ResolveProc)GetProcAddress(handle,"hx_cffi");
 | 
						|
            if (sResolveProc==0)
 | 
						|
               FreeLibrary(handle);
 | 
						|
         }
 | 
						|
      }
 | 
						|
      #endif
 | 
						|
 | 
						|
      #ifdef NEKO_COMPATIBLE
 | 
						|
      if (sResolveProc==0)
 | 
						|
      {
 | 
						|
         sResolveProc = InitDynamicNekoLoader();
 | 
						|
      }
 | 
						|
      #endif
 | 
						|
 | 
						|
      if (sResolveProc==0)
 | 
						|
      {
 | 
						|
         fprintf(stderr,"Could not link plugin to process (hxCFFILoader.h %d)\n",__LINE__);
 | 
						|
         exit(1);
 | 
						|
      }
 | 
						|
      return ResolveDefault(inName);
 | 
						|
   }
 | 
						|
 | 
						|
   #else // windows }  { not windows
 | 
						|
 | 
						|
 | 
						|
   void *LoadFunc(const char *inName)
 | 
						|
   {
 | 
						|
      #ifndef ANDROID // {
 | 
						|
         if (sResolveProc==0)
 | 
						|
         {
 | 
						|
            sResolveProc = (ResolveProc)dlsym(RTLD_DEFAULT,"hx_cffi");
 | 
						|
         }
 | 
						|
 | 
						|
         #ifdef NEKO_COMPATIBLE
 | 
						|
         if (sResolveProc==0)
 | 
						|
         {
 | 
						|
            sResolveProc = InitDynamicNekoLoader();
 | 
						|
         }
 | 
						|
         #endif
 | 
						|
      #endif // !Android  }
 | 
						|
 | 
						|
      if (sResolveProc==0)
 | 
						|
      {
 | 
						|
         #ifdef ANDROID
 | 
						|
         __android_log_print(ANDROID_LOG_ERROR, "CFFILoader.h", "Could not API %s", inName);
 | 
						|
         return 0;
 | 
						|
         #else
 | 
						|
         #ifdef NEKO_COMPATIBLE
 | 
						|
         fprintf(stderr,"Could not link plugin to process (CFFILoader.h %d) - with neko\n",__LINE__);
 | 
						|
         #else
 | 
						|
         fprintf(stderr,"Could not link plugin to process (CFFILoader.h %d)\n",__LINE__);
 | 
						|
         #endif
 | 
						|
         exit(1);
 | 
						|
         #endif
 | 
						|
      }
 | 
						|
      return ResolveDefault(inName);
 | 
						|
   }
 | 
						|
 | 
						|
   #undef EXT
 | 
						|
 | 
						|
   #endif // not windows }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
   #ifndef ANDROID // not android {
 | 
						|
 | 
						|
   #define DEFFUNC(name,ret,def_args,call_args) \
 | 
						|
   typedef ret (*FUNC_##name)def_args; \
 | 
						|
   extern FUNC_##name name; \
 | 
						|
   ret IMPL_##name def_args \
 | 
						|
   { \
 | 
						|
      name = (FUNC_##name)LoadFunc(#name); \
 | 
						|
      if (!name) \
 | 
						|
      { \
 | 
						|
         fprintf(stderr,"Could not find function:" #name " \n"); \
 | 
						|
         exit(1); \
 | 
						|
      } \
 | 
						|
      return name call_args; \
 | 
						|
   }\
 | 
						|
   FUNC_##name name = IMPL_##name;
 | 
						|
    
 | 
						|
   #ifdef NEKO_COMPATIBLE
 | 
						|
   DEFINE_PRIM(neko_init,5)
 | 
						|
   #endif
 | 
						|
 | 
						|
   #else // not android }  { android
 | 
						|
 | 
						|
 | 
						|
   #define DEFFUNC(name,ret,def_args,call_args) \
 | 
						|
   typedef ret (*FUNC_##name)def_args; \
 | 
						|
   extern FUNC_##name name; \
 | 
						|
   ret IMPL_##name def_args \
 | 
						|
   { \
 | 
						|
      name = (FUNC_##name)LoadFunc(#name); \
 | 
						|
      if (!name) \
 | 
						|
      { \
 | 
						|
         __android_log_print(ANDROID_LOG_ERROR,"CFFILoader", "Could not find function:" #name "\n"); \
 | 
						|
      } \
 | 
						|
      return name call_args; \
 | 
						|
   }\
 | 
						|
   FUNC_##name name = IMPL_##name;
 | 
						|
    
 | 
						|
 | 
						|
   #endif // android }
 | 
						|
 | 
						|
#endif // dynamic link }
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
 |