@Olly;
That works. At least it works for arrays. I couldn't get it to work for Strings yet. Simba possibly allocates strings differently than arrays (I tried shortstring, ansistring, string: http://wiki.freepascal.org/Character_and_string_types). I used calling convention from: https://en.wikipedia.org/wiki/X86_ca...rland_register otherwise it crashes.
Will have to look into why string doesn't work later.
MemoryManager.hxx
C++ Code:
#ifndef MEMORYMANAGER_HXX_INCLUDED
#define MEMORYMANAGER_HXX_INCLUDED
#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 // MEMORYMANAGER_HXX_INCLUDED
Exports.hxx:
C++ Code:
#ifndef EXPORTS_HXX_INCLUDED
#define EXPORTS_HXX_INCLUDED
#include <cstdint>
#include <cstdio>
#include <new>
#include "MemoryManager.hxx"
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#define DLL_FUNC __declspec(dllexport)
#else
#define DLL_FUNC
#endif
extern HMODULE module;
//extern TMemoryManager PLUGIN_MEMORY_MANAGER;
static const char* PascalExports[] =
{
"GetData", "Function GetPluginData(): array of char;" //array of char works. string, ansistring, shortstring does not.
};
static const char* PascalTypes[] =
{
"", ""
};
static const long int PascalExportCount = sizeof(PascalExports) / (sizeof(PascalExports[0]) * 2);
static const long int PascalTypeCount = 0;
#ifdef __cplusplus
extern "C"
{
#endif
DLL_FUNC int GetPluginABIVersion();
DLL_FUNC int GetFunctionCount();
DLL_FUNC int GetTypeCount();
DLL_FUNC int GetFunctionInfo(int Index, void** Address, char** Definition);
DLL_FUNC int GetTypeInfo(int Index, char** Type, char** Definition);
DLL_FUNC void SetPluginMemManager(TMemoryManager MemMgr);
DLL_FUNC void OnAttach(void* info);
DLL_FUNC void OnDetach();
DLL_FUNC void* GetData();
#ifdef __cplusplus
}
#endif
#endif // EXPORTS_HXX_INCLUDED
Exports.cxx
C++ Code:
#include "Exports.hxx"HMODULE module
= nullptr
;TMemoryManager PLUGIN_MEMORY_MANAGER
= {0};int GetPluginABIVersion
(){ return 2;}int GetFunctionCount
(){ return PascalExportCount
;}int GetTypeCount
(){ return PascalTypeCount
;}int GetFunctionInfo
(int Index
, void** Address
, char** Definition
){ if (Index
< PascalExportCount
) { #if defined(_WIN32) || defined(_WIN64) *Address
= (void*)GetProcAddress
(module
, PascalExports
[Index
* 2]); #else *Address
= (void*)dlsym
(RTLD_DEFAULT
, PascalExports
[Index
* 2]); #endif strcpy(*Definition
, PascalExports
[Index
* 2 + 1]); return Index
; } return -1;}int GetTypeInfo
(int Index
, char** Type
, char** Definition
){ if (Index
< PascalTypeCount
) { strcpy(*Type
, PascalTypes
[Index
* 2 + 0]); strcpy(*Definition
, PascalTypes
[Index
* 2 + 1]); return Index
; } return -1;}void SetPluginMemManager
(TMemoryManager MemMgr
){ PLUGIN_MEMORY_MANAGER
= MemMgr
;}void OnAttach
(void* info
){}void OnDetach
(){}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
* Allocate
(std
::size_t size
, std
::size_t element_size
= sizeof(T
)){ std
::size_t new_size
= (size
* element_size
) + (sizeof(int) * 2); std
::int32_t* ptr
= static_cast
<std
::int32_t*>(PLUGIN_MEMORY_MANAGER.
AllocMem(new_size
)); *ptr
++ = 1; //ref_count *ptr
++ = size
- 1; //data_size return reinterpret_cast
<T
*>(ptr
);}void* GetData
(){ const char* res
= "Hello World!"; char* str
= Allocate
<char
>(strlen(res
)); strcpy(&str
[0], &res
[0]); return &str
[0];}