Skip to content

Commit

Permalink
Some plugin docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Sep 13, 2023
1 parent 8c1180f commit c0ccb11
Show file tree
Hide file tree
Showing 13 changed files with 1,871 additions and 291 deletions.
410 changes: 410 additions & 0 deletions DocGen/build/plugins/Plugins.html

Large diffs are not rendered by default.

501 changes: 501 additions & 0 deletions DocGen/build/plugins/c++.html

Large diffs are not rendered by default.

310 changes: 310 additions & 0 deletions DocGen/build/plugins/index.html

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions DocGen/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
html_css_files = ['custom.css']
extensions = [
'sphinx.ext.githubpages',
'sphinx.ext.mathjax'
]
'sphinx.ext.mathjax',
'sphinx.ext.autosectionlabel'
]
1 change: 1 addition & 0 deletions DocGen/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ Simba

tutorials/index
api/index
plugins/index
113 changes: 113 additions & 0 deletions DocGen/source/plugins/Plugins.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
###############
Writing Plugins
###############

Simba scripts can be extended with plugins.
Plugins are libraries (dll/so/dylib) which can be written in virtually every low-level language.

.. note::

For 32bit the **cdecl** calling convention is used for methods plugin related. Otherwise the default systems calling convention is used.

-----

Importing functions
-------------------

To import functions the following methods must be exported to provide information to Simba.

.. code-block::
function GetFunctionInfo(Index: Integer; var Address: Pointer; var Header: PChar): Integer; cdecl;
function GetFunctionCount: Integer; cdecl;
.. note::

| Appending :code:`native;` to the header cause parameters and result passed in the lape wrapper format.
| This is the preferred way, otherwise libffi is used.
The Lape wrapper format is:

.. code-block::
procedure(const Params: PParamArray; const Result: Pointer);
-----

Importing types
---------------

To import types the following methods must be exported to provide information to Simba.

.. code-block::
function GetTypeInfo(Index: Integer; var Name: PChar; var Str: PChar): Integer; cdecl;
function GetTypeCount: Integer; cdecl;
.. note::

These methods are imported before GetFunctionInfo & GetFunctionCount so these types will be available when adding functions.

-----

Importing code
--------------

Code can be imported in the script with the following methods exported.

.. code-block::
procedure GetCode(var Code: PChar); cdecl;
function GetCodeLength: Integer; cdecl;
-----

RegisterSimbaPlugin
-------------------

A plugin can export `RegisterSimbaPlugin` which provides access to various Simba's infomation & methods.

.. code-block::
procedure RegisterSimbaPlugin(Infomation: PSimbaInfomation; Methods: PSimbaMethods); cdecl;
These pointers are provided to these structures:

.. code-block::
TSimbaInfomation = packed record
SimbaVersion: Integer;
SimbaMajor: Integer;
FileName: PChar;
Compiler: Pointer;
end;
TSimbaMethods = packed record
RunOnMainThread: procedure(Method: TMainThreadMethod; Data: Pointer = nil); cdecl;
GetMem: function(Size: NativeUInt): Pointer; cdecl;
FreeMem: function(P: Pointer): NativeUInt; cdecl;
AllocMem: function(Size: NativeUInt): Pointer; cdecl;
ReAllocMem: function(var P: Pointer; Size: NativeUInt): Pointer; cdecl;
MemSize: function(P: Pointer): NativeUInt; cdecl;
RaiseException: procedure(Message: PChar); cdecl;
GetTypeInfo: function(Compiler: Pointer; Typ: PChar): Pointer; cdecl;
GetTypeInfoSize: function(TypeInfo: Pointer): NativeInt; cdecl;
GetTypeInfoFieldOffset: function(TypeInfo: Pointer; FieldName: PChar): NativeInt; cdecl;
AllocateRawArray: function(ElementSize, Len: NativeInt): Pointer; cdecl;
ReAllocateRawArray: procedure(var Arr: Pointer; ElementSize, NewLen: NativeInt); cdecl;
AllocateArray: function(TypeInfo: Pointer; Len: NativeInt): Pointer; cdecl;
AllocateString: function(Data: PChar): Pointer; cdecl;
AllocateUnicodeString: function(Data: PUnicodeChar): Pointer; cdecl;
SetArrayLength: procedure(TypeInfo: Pointer; var AVar: Pointer; NewLen: NativeInt); cdecl;
GetArrayLength: function(AVar: Pointer): NativeInt; cdecl;
end;
See the :ref:`Example C++ plugin` to see how TypeInfo is used to allocate custom records & arrays.
201 changes: 201 additions & 0 deletions DocGen/source/plugins/c++.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
##################
Example C++ plugin
##################

main.h
------

.. code-block:: c++

#ifndef __MAIN_H__
#define __MAIN_H__

#include <cstdint>

#if defined(_WIN32) || defined(_WIN64)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT [[gnu::visibility("default")]]
#endif

#if INTPTR_MAX == INT32_MAX
typedef int32_t NativeInt;
typedef uint32_t NativeUInt;
#else
typedef int64_t NativeInt;
typedef uint64_t NativeUInt;
#endif

struct __attribute__((__packed__)) TSimbaInfo
{
int SimbaVersion;
int SimbaMajor;

char* FileName;

void* Compiler;
};

struct __attribute__((__packed__)) TSimbaMethods
{
void (*RunOnMainThread)(void(*Method)(void*), void* data);

void* (*GetMem)(NativeUInt size);
void (*FreeMem)(void* ptr);
void* (*AllocMem)(NativeUInt Size);
void* (*ReAllocMem)(void** ptr, NativeUInt size);
NativeUInt (*MemSize)(void* ptr);

void (*RaiseException)(char* Message);
void* (*GetTypeInfo)(void* Compiler, char* Typ);
NativeUInt (*GetTypeInfoSize)(void* TypeInfo);
NativeInt (*GetTypeInfoFieldOffset)(void* TypeInfo, char* FieldName);

void* (*AllocateRawArray)(NativeInt ElementSize, NativeUInt Len);
void (*ReAllocateRawArray)(void** ptr, NativeInt ElementSize, NativeUInt Len);

void* (*AllocateArray)(void* TypeInfo, NativeUInt Len);
void* (*AllocateString)(void* Data);
void* (*AllocateUnicodeString)(void* Data);

void (*SetArrayLength)(void* TypeInfo, void**ptr, NativeInt NewLen);
NativeInt (*GetArrayLength)(void* AVar);
};

TSimbaInfo* SIMBA_INFO = {0};
TSimbaMethods* SIMBA_METHODS = {0};

extern "C"
{
EXPORT int GetTypeCount();
EXPORT int GetTypeInfo(int Index, char** Name, char** Definition);
EXPORT int GetFunctionCount();
EXPORT int GetFunctionInfo(int Index, void** Address, char** Definition);
EXPORT void RegisterSimbaPlugin(TSimbaInfo* Information, TSimbaMethods* Methods);
}

#endif // __MAIN_H__
main.cpp
--------

.. code-block:: c++

#include "main.h"
#include "stdio.h"
#include <cstring>

template<typename T>
void MemWrite(void* ptr, int offset, T item) noexcept
{
memcpy((char*)ptr+offset, &item, sizeof(T));
}

template<typename T>
T MemRead(void* ptr) noexcept
{
T result;
memcpy(&result, ptr, sizeof(T));
return result;
}

void* ARR_TYPEINFO = 0;
void* REC_TYPEINFO = 0;
NativeUInt REC_SIZE = 0;
NativeUInt REC_STR_OFFSET = 0;

void GetIntArray(void** Params, void** Result)
{
int Count = MemRead<int>(*Params);
void* Arr = SIMBA_METHODS->AllocateRawArray(sizeof(int32_t), Count);
for (int i=0; i<Count; i++) {
MemWrite(Arr, i*sizeof(int), i);
}
MemWrite<void*>(Result, 0, Arr);
}

void GetRecord(void** Params, void** Result)
{
MemWrite<int>(Result, 0, 123456);
MemWrite<void*>(Result, REC_STR_OFFSET, SIMBA_METHODS->AllocateString((char*)"Hello world"));
}

void GetArrayOfRecord(void** Params, void** Result)
{
char str0[] = "Hello in array index 0";
char str1[] = "Hola in array index 1";
char str2[] = "Bonjour in array index 2";

void* mem = SIMBA_METHODS->AllocateArray(ARR_TYPEINFO, 3);
for (int i=0; i<3; i++) {
void* str = nullptr;
switch (i) {
case 0: str = SIMBA_METHODS->AllocateString((void*)str0); break;
case 1: str = SIMBA_METHODS->AllocateString((void*)str1); break;
case 2: str = SIMBA_METHODS->AllocateString((void*)str2); break;
}

// write arr[i].i
MemWrite<int>(mem, i*REC_SIZE, i);
// write arr[i].str
MemWrite<void*>(mem, (i*REC_SIZE)+REC_STR_OFFSET, str);
}

MemWrite<void*>(Result, 0, mem);
}

void RegisterSimbaPlugin(TSimbaInfo* Info, TSimbaMethods* Methods)
{
SIMBA_INFO = Info;
SIMBA_METHODS = Methods;

REC_TYPEINFO = SIMBA_METHODS->GetTypeInfo(SIMBA_INFO->Compiler, (char*)"TMyRecord");
REC_SIZE = SIMBA_METHODS->GetTypeInfoSize(REC_TYPEINFO);
REC_STR_OFFSET = SIMBA_METHODS->GetTypeInfoFieldOffset(REC_TYPEINFO, (char*)"str");

ARR_TYPEINFO = SIMBA_METHODS->GetTypeInfo(SIMBA_INFO->Compiler, (char*)"array of TMyRecord");
}

int GetTypeCount()
{
return 1;
}

int GetTypeInfo(int Index, char** Name, char** Definition)
{
switch(Index) {
case 0:
strcpy(*Name, "TMyRecord");
strcpy(*Definition, "record i: Int32; str: String; end;");
break;
}
return Index;
}
int GetFunctionCount()
{
return 3;
}

int GetFunctionInfo(int Index, void** Address, char** Definition)
{
switch(Index) {
case 0:
strcpy(*Definition, "function GetIntArray(Count: Int32): array of Int32; native;");
*Address = (void*)GetIntArray;
break;

case 1:
strcpy(*Definition, "function GetRecord: TMyRecord; native;");
*Address = (void*)GetRecord;
break;

case 2:
strcpy(*Definition, "function GetArrayOfRecord: array of TMyRecord; native;");
*Address = (void*)GetArrayOfRecord;
break;
}

return Index;
}


8 changes: 8 additions & 0 deletions DocGen/source/plugins/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Plugins
=======

.. toctree::
:maxdepth: 2

Plugins.rst
c++.rst
3 changes: 1 addition & 2 deletions DocGen/source/tutorials/index.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

Simba
=====

.. toctree::
:maxdepth: 2

Color Finding.rst
Sleep Until.rst
Sleep Until.rst
6 changes: 5 additions & 1 deletion Source/Simba.lpi
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@
<PackageName Value="LCL"/>
</Item5>
</RequiredPackages>
<Units Count="140">
<Units Count="141">
<Unit0>
<Filename Value="Simba.lpr"/>
<IsPartOfProject Value="True"/>
Expand Down Expand Up @@ -983,6 +983,10 @@
<Filename Value="codetools/simba.ide_codetools_keywords.pas"/>
<IsPartOfProject Value="True"/>
</Unit139>
<Unit140>
<Filename Value="script/simba.script_pluginmethods.pas"/>
<IsPartOfProject Value="True"/>
</Unit140>
</Units>
</ProjectOptions>
<CompilerOptions>
Expand Down
4 changes: 2 additions & 2 deletions Source/forms/simba.functionlistform.lfm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
object SimbaFunctionListForm: TSimbaFunctionListForm
Left = 2036
Left = 1446
Height = 301
Top = 685
Width = 175
Width = 765
Caption = 'Function List'
DesignTimePPI = 120
LCLVersion = '3.0.0.1'
Expand Down
Loading

0 comments on commit c0ccb11

Please sign in to comment.