Skip to content

Instantly share code, notes, and snippets.

@Brandon-T
Last active May 4, 2020 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Brandon-T/5e62785acbc949728acef4933c66a319 to your computer and use it in GitHub Desktop.
Save Brandon-T/5e62785acbc949728acef4933c66a319 to your computer and use it in GitHub Desktop.
#include "PascalExports.hxx"
void HelloWorld(void** Params, void** Result);
{
std::string my_str = "Hello World";
char* str = AllocateString<char>(my_str.length() + 1);
strcpy(str, my_str.c_str());
*static_cast<char**>(Result) = str; //return str
}
void GetStuff(void** Params, void** Result)
{
char* str = GetString(Params[0]);
printf("String: %s\n", str);
size_t array_size = 0;
int* int_array = GetArray<int>(Params[1], &array_size);
for (int i = 0; i < array_size; ++i)
{
printf("%d ", int_array[i]);
}
*reinterpret_cast<int*>(Result) = -1; //return a single int..
*reinterpret_cast<int**>(Result) = AllocateArray<int>(100); //return an array of 100 ints..
}
//more examples..
int main()
{
int* foo = AllocateArray<int>(100);
float* bar = AllocateArray<float>(100);
char* str = AllocateString<char>(100);
for (int i = 0; i < 100; ++i)
{
foo[i] = i + 1;
}
for (int i = 0; i < 100; ++i)
{
bar[i] = i + 1.0;
}
strcpy(str, "hello world - pascal");
}
#define EXPORT __declspec(dllexport)
#ifdef __cplusplus
extern "C"
{
#endif
EXPORT int GetPluginABIVersion();
EXPORT int GetFunctionCount();
EXPORT int GetTypeCount();
EXPORT int GetFunctionInfo(int Index, void** Address, char** Definition);
EXPORT int GetTypeInfo(int Index, char** Type, char** Definition);
#if !defined(_MSC_VER)
EXPORT void SetPluginMemManager(TMemoryManager MemMgr);
#endif
EXPORT void SetPluginSimbaMethods(TSimbaMethods Methods);
EXPORT void SetPluginSimbaMemoryAllocators(TSimbaMemoryAllocators Allocators);
EXPORT void OnAttach(void* info);
EXPORT void OnDetach();
#ifdef __cplusplus
}
#endif
#if !defined(_MSC_VER)
TMemoryManager PLUGIN_MEMORY_MANAGER = {0};
#endif
TSimbaMethods PLUGIN_SYNC_METHODS = {0};
TSimbaMemoryAllocators PLUGIN_MEMORY_ALLOCATORS = {0};
#if !defined(_MSC_VER)
void SetPluginMemManager(TMemoryManager MemMgr)
{
PLUGIN_MEMORY_MANAGER = MemMgr;
}
#endif
void SetPluginSimbaMethods(TSimbaMethods Methods)
{
PLUGIN_SYNC_METHODS = Methods;
}
void SetPluginSimbaMemoryAllocators(TSimbaMemoryAllocators Allocators)
{
PLUGIN_MEMORY_ALLOCATORS = Allocators;
}
#include <cstdint>
#if !defined(_MSC_VER)
#define DELPHI_CALLING_CONVENTION __attribute__((regparm(3)))
typedef struct
{
std::uint32_t TotalAddressSpace;
std::uint32_t TotalUncommited;
std::uint32_t TotalCommited;
std::uint32_t TotalAllocated;
std::uint32_t TotalFree;
std::uint32_t FreeSmall;
std::uint32_t FreeBig;
std::uint32_t Unused;
std::uint32_t Overhead;
std::uint32_t HeapErrorCode;
} THeapStatus;
typedef struct
{
std::uintptr_t MaxHeapSize;
std::uintptr_t MaxHeapUsed;
std::uintptr_t CurrHeapSize;
std::uintptr_t CurrHeapUsed;
std::uintptr_t CurrHeapFree;
} TFPCHeapStatus;
typedef struct
{
bool NeedLock;
void* (*GetMem)(std::intptr_t size) DELPHI_CALLING_CONVENTION;
std::intptr_t (*FreeMem)(void* &ptr) DELPHI_CALLING_CONVENTION;
std::intptr_t (*FreeMemSize)(void* &ptr, std::intptr_t size) DELPHI_CALLING_CONVENTION;
void* (*AllocMem)(std::intptr_t size) DELPHI_CALLING_CONVENTION;
void* (*ReAllocMem)(void* &ptr, std::intptr_t size) DELPHI_CALLING_CONVENTION;
std::intptr_t (*MemSize)(void* ptr) DELPHI_CALLING_CONVENTION;
void (*InitThread)() DELPHI_CALLING_CONVENTION;
void (*DoneThread)() DELPHI_CALLING_CONVENTION;
void (*RelocateHeap)() DELPHI_CALLING_CONVENTION;
THeapStatus (*GetHeapStatus)() DELPHI_CALLING_CONVENTION;
TFPCHeapStatus (*GetFPCHeapStatus)() DELPHI_CALLING_CONVENTION;
} TMemoryManager;
typedef struct
{
bool NeedLock;
void* (*GetMem)(std::intptr_t size) DELPHI_CALLING_CONVENTION;
std::intptr_t (*FreeMem)(void* &ptr) DELPHI_CALLING_CONVENTION;
std::intptr_t (*FreeMemSize)(void* &ptr, std::intptr_t size) DELPHI_CALLING_CONVENTION;
void* (*AllocMem)(std::intptr_t size) DELPHI_CALLING_CONVENTION;
void* (*ReAllocMem)(void* &ptr, std::intptr_t size) DELPHI_CALLING_CONVENTION;
std::intptr_t (*MemSize)(void* ptr) DELPHI_CALLING_CONVENTION;
void (*InitThread)() DELPHI_CALLING_CONVENTION;
void (*DoneThread)() DELPHI_CALLING_CONVENTION;
void (*RelocateHeap)() DELPHI_CALLING_CONVENTION;
THeapStatus (*GetHeapStatus)() DELPHI_CALLING_CONVENTION;
TFPCHeapStatus (*GetFPCHeapStatus)() DELPHI_CALLING_CONVENTION;
} __attribute__((__packed__)) TCMemoryManager;
#endif
typedef struct
{
void (__cdecl *Sync)(void(__cdecl *synchronize_method)(void*), void* data);
} __attribute__((__packed__)) TSimbaMethods;
typedef struct
{
void* (__cdecl *GetMem)(std::size_t size);
void (__cdecl *FreeMem)(void* ptr);
} __attribute__((__packed__)) TSimbaMemoryAllocators;
typedef struct
{
std::make_signed_t<std::size_t> refCount;
std::make_signed_t<std::size_t> length;
char data[];
} __attribute__((__packed__)) PascalArray;
#if defined(FPC2)
typedef struct
{
std::make_signed_t<std::size_t> refCount;
std::make_signed_t<std::size_t> length;
char data[];
} __attribute__((__packed__)) PascalString;
#else
typedef struct
{
std::uint16_t codePage;
std::uint16_t elementSize;
#if defined(__x86_64__)
std::uint32_t dummy;
#endif
std::make_signed_t<std::size_t> refCount;
std::make_signed_t<std::size_t> length;
char data[];
} __attribute__((__packed__)) PascalString;
#endif // defined
template<typename T, std::size_t size>
struct __attribute__((__packed__)) StaticPascalArray
{
const std::make_signed_t<std::size_t> refCount = -1;
const std::make_signed_t<std::size_t> length = size;
T data[size] = {0};
};
template<typename T>
int PascalHigh(T* Arr)
{
return reinterpret_cast<int*>(Arr)[-1];
}
template<typename T>
int PascalLength(T* Arr)
{
return PascalHigh<T>(Arr) + 1;
}
template<typename T>
T* AllocateArray(std::size_t size, std::size_t element_size = sizeof(T))
{
std::size_t new_size = (size * element_size) + sizeof(PascalArray);
#if !defined(_MSC_VER)
PascalArray* ptr = static_cast<PascalArray*>(PLUGIN_MEMORY_MANAGER.AllocMem(new_size));
#else
PascalArray* ptr = static_cast<PascalArray*>(PLUGIN_MEMORY_ALLOCATORS.GetMem(new_size));
#endif
ptr->refCount = 1;
ptr->length = size - 1;
return reinterpret_cast<T*>(++ptr);
}
template<typename T>
T* AllocateString(std::size_t size, std::size_t element_size = sizeof(T))
{
std::size_t new_size = (size * element_size) + sizeof(PascalString);
#if !defined(_MSC_VER)
PascalString* ptr = static_cast<PascalString*>(PLUGIN_MEMORY_MANAGER.AllocMem(new_size + 1));
#else
PascalString* ptr = static_cast<PascalString*>(PLUGIN_MEMORY_ALLOCATORS.GetMem(new_size + 1));
#endif
ptr->refCount = 1;
ptr->length = size;
return reinterpret_cast<T*>(++ptr);
}
template<typename T>
T* GetArray(void* ptr, std::size_t* size)
{
PascalArray* mem = static_cast<PascalArray*>(ptr);
return reinterpret_cast<T*>((--mem)->data);
}
template<typename T>
T* GetString(void* ptr)
{
PascalString* mem = static_cast<PascalString*>(ptr);
return reinterpret_cast<T*>((--mem)->data);
}
#if !defined(_MSC_VER)
extern TMemoryManager PLUGIN_MEMORY_MANAGER;
#endif
extern TSimbaMethods PLUGIN_SYNC_METHODS;
extern TSimbaMemoryAllocators PLUGIN_MEMORY_ALLOCATORS;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment