forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
330
Kha/Backends/Kinc-hxcpp/khacpp/include/hx/CFFILoader.h
Normal file
330
Kha/Backends/Kinc-hxcpp/khacpp/include/hx/CFFILoader.h
Normal file
@ -0,0 +1,330 @@
|
||||
#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
|
||||
|
||||
|
Reference in New Issue
Block a user