├── .gitignore ├── LICENSE.md ├── README.md ├── examples └── Test │ └── src │ └── Test.pas └── godot ├── internal └── GDNativeApi.pas └── types ├── GodotArray.pas ├── GodotObject.pas ├── GodotString.pas └── GodotVariant.pas /.gitignore: -------------------------------------------------------------------------------- 1 | # Gitignore 2 | 3 | # Library output: 4 | *.so 5 | # Compilation files: 6 | *.o 7 | *.ppu 8 | 9 | # Directories: 10 | **/bin/ 11 | **/lib/ 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2019 Benedikt Magnus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GDNative with Object Pascal 2 | ======= 3 | Object Pascal bindings for the 4 | [GDNative interface](https://github.com/GodotNativeTools/godot_headers) of the [Godot Engine](https://godotengine.org/). 5 | 6 | ## This is a very new library. It does proof that it works, but do not expect any more yet. -------------------------------------------------------------------------------- /examples/Test/src/Test.pas: -------------------------------------------------------------------------------- 1 | library Test; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | uses 6 | {$IFDEF UNIX} 7 | {$IFDEF UseCThreads} 8 | cthreads, 9 | {$ENDIF} 10 | {$ENDIF} 11 | GDNativeApi, 12 | GodotObject, 13 | GodotVariant, 14 | GodotArray; 15 | 16 | function TestConstructor (GodotObject: PGodotObject; MethodData: Pointer): Pointer; cdecl; 17 | begin 18 | WriteLn('TestConstructor called.'); 19 | 20 | Result := nil; 21 | end; 22 | 23 | procedure TestDestructor (GodotObject: PGodotObject; MethodData, UserData: Pointer); cdecl; 24 | begin 25 | WriteLn('TestDestructor called.'); 26 | end; 27 | 28 | function TestReady (GodotObject: PGodotObject; MethodData, UserData: Pointer; ParameterCount: Integer; Parameters: PPGodotVariant): TGodotVariant; cdecl; 29 | begin 30 | WriteLn('TestReady called.'); 31 | 32 | GodotGDNativeCoreApi.GodotVariantNewNil(@Result); 33 | end; 34 | 35 | procedure godot_gdnative_init (OptionsPointer: PGodotGDNativeInitOptions); cdecl; 36 | var 37 | Options: TGodotGDNativeInitOptions; 38 | begin 39 | WriteLn('gdnative_init called.'); 40 | 41 | Options := OptionsPointer^; 42 | 43 | GodotApiExtraction(Options.GodotGDNativeCoreApi); 44 | end; 45 | 46 | procedure godot_gdnative_terminate (Options: Pointer); cdecl; 47 | begin 48 | WriteLn('gdnative_terminate called.'); 49 | end; 50 | 51 | procedure godot_nativescript_init (GDNativeHandle: Pointer); cdecl; 52 | var 53 | CreateFunction: TGodotInstanceCreateFunction; 54 | DestroyFunction: TGodotInstanceDestroyFunction; 55 | Method: TGodotInstanceMethod; 56 | Attributes: TGodotMethodAttributes; 57 | ClassName, BaseClass, FunctionName: PChar; 58 | begin 59 | WriteLn('Nativescript_init called.'); 60 | 61 | CreateFunction := Default(TGodotInstanceCreateFunction); 62 | CreateFunction.CreateFunction := @TestConstructor; 63 | 64 | DestroyFunction := Default(TGodotInstanceDestroyFunction); 65 | DestroyFunction.DestroyFunction := @TestDestructor; 66 | 67 | ClassName := 'TestClass'; 68 | BaseClass := 'Node'; 69 | 70 | GodotGDNativeExtensionNativescriptApi.GodotNativescriptRegisterClass(GDNativeHandle, ClassName, BaseClass, CreateFunction, DestroyFunction); 71 | 72 | Method := Default(TGodotInstanceMethod); 73 | Method.Method := @TestReady; 74 | 75 | Attributes.RpcType := GodotMethodRpcModeDisabled; 76 | 77 | FunctionName := '_ready'; 78 | 79 | GodotGDNativeExtensionNativescriptApi.GodotNativescriptRegisterMethod(GDNativeHandle, ClassName, FunctionName, Attributes, Method); 80 | end; 81 | 82 | function some_test_procedure (Data: Pointer; Parameters: PGodotArray): TGodotVariant; cdecl; 83 | var 84 | TestInt: TGodotVariant; 85 | begin 86 | GodotGDNativeCoreApi.GodotVariantNewInt(@TestInt, 42); 87 | Result := TestInt; 88 | end; 89 | 90 | exports 91 | godot_gdnative_init, 92 | godot_gdnative_terminate, 93 | godot_nativescript_init, 94 | some_test_procedure; 95 | 96 | end. -------------------------------------------------------------------------------- /godot/internal/GDNativeApi.pas: -------------------------------------------------------------------------------- 1 | unit GDNativeApi; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | {$IFDEF FPC} 6 | {$PACKRECORDS C} 7 | {$ENDIF} 8 | 9 | interface 10 | 11 | uses 12 | GodotObject, 13 | GodotVariant; 14 | 15 | const 16 | GodoApiVersion = 1; 17 | 18 | // API core and extension types: 19 | const 20 | // The core API type: 21 | GDNativeCore = 0; 22 | // The extension API types: 23 | GDNativeExtensionNativescript = 1; 24 | GDNativeExtensionPluginscript = 2; 25 | GDNativeExtensionAndroid = 3; 26 | GDNativeExtensionARVR = 4; 27 | GDNativeExtensionVideorecord = 5; 28 | GDNativeExtensionNet = 6; 29 | // The number of extensions: 30 | GDNativeExtensionCount = 6; 31 | 32 | // Method RPC modes: 33 | // Attention: Muste be an enum because Godot does not use cardinals for this type! 34 | type 35 | GodotMethodRpcMode = ( 36 | GodotMethodRpcModeDisabled, 37 | GodotMethodRpcModeRemote, 38 | GodotMethodRpcModeMaster, 39 | GodotMethodRpcModePuppet, 40 | GodotMethodRpcModeRemotesync, 41 | GodotMethodRpcModeMastersync, 42 | GodotMethodRpcModePuppetsync 43 | ); 44 | const 45 | GodotMethodRpcModeSlave = GodotMethodRpcModePuppet; 46 | GodotMethodRpcModeSync = GodotMethodRpcModeRemotesync; 47 | 48 | type 49 | TReportVersionMismatch = procedure (LibraryPointer: PGodotObject; Reason: PChar; ExpectedVersion, FoundVersion: TGodotGDNativeApiVersion); cdecl; 50 | TReportLoadingError = procedure (LibraryPointer: PGodotObject; Reason: PChar); cdecl; 51 | 52 | type 53 | PGodotGDNativeInitOptions = ^TGodotGDNativeInitOptions; 54 | TGodotGDNativeInitOptions = record 55 | InEditor: Boolean; 56 | CoreApiHash: Int64; 57 | EditorApiHash: UInt64; 58 | NoApiHash: UInt64; 59 | ReportVersionMismatch: TReportVersionMismatch; 60 | ReportLoadingError: TReportLoadingError; 61 | GDNativeLibrary: PGodotObject; // Pointer to the GDNativeLibrary that is being initialised. 62 | GodotGDNativeCoreApi: PGodotGDNativeCoreApi; 63 | ActiveLibraryPath: PGodotString; 64 | end; 65 | 66 | // Method instance functions: 67 | type 68 | TCreateFunction = function (InstancePointer: PGodotObject; MethodData: Pointer): Pointer; cdecl; // Returns UserData 69 | TDestroyFunction = procedure (InstancePointer: PGodotObject; MethodData, UserData: Pointer); cdecl; 70 | TMethod = function (InstancePointer: PGodotObject; MethodData, UserData: Pointer; ParameterCount: Integer; Parameters: PPGodotVariant): TGodotVariant; cdecl; 71 | TFreeFunction = procedure (Parameter: Pointer); 72 | 73 | // Method related records: 74 | type 75 | TGodotInstanceCreateFunction = record 76 | CreateFunction: TCreateFunction; 77 | MethodData: Pointer; 78 | FreeFunction: TFreeFunction; 79 | end; 80 | TGodotInstanceDestroyFunction = record 81 | DestroyFunction: TDestroyFunction; 82 | MethodData: Pointer; 83 | FreeFunction: TFreeFunction; 84 | end; 85 | TGodotMethodAttributes = record 86 | RpcType: GodotMethodRpcMode; 87 | end; 88 | TGodotInstanceMethod = record 89 | Method: TMethod; // NOTE: If we change this to a generic pointer type, we could put in any function/procedure, even static ones from classes... 90 | MethodData: Pointer; 91 | FreeFuncton: TFreeFunction; 92 | end; 93 | 94 | // API related records: 95 | type 96 | TGodotGDNativeApiVersion = record 97 | Major: Cardinal; 98 | Minor: Cardinal; 99 | end; 100 | 101 | // API header: 102 | type 103 | PGodotGDNativeApiHeader = ^TGodotGDNativeApiHeader; 104 | TGodotGDNativeApiHeader = record 105 | ApiType: Cardinal; 106 | ApiVersion: TGodotGDNativeApiVersion; 107 | Next: PGodotGDNativeApiHeader; 108 | end; 109 | 110 | // API helper types: 111 | type 112 | PGDNativeApiExtensionArray = ^TGDNativeApiExtensionArray; 113 | TGDNativeApiExtensionArray = Array[0..GDNativeExtensionCount-1] of PGodotGDNativeApiHeader; 114 | 115 | // API functions: 116 | type 117 | TGodotNativescriptRegisterClass = procedure (GDNativeHandle: Pointer; ClassName: PChar; BaseClass: PChar; 118 | CreateFunction: TGodotInstanceCreateFunction; 119 | DestroyFunction: TGodotInstanceDestroyFunction); cdecl; 120 | TGodotNativescriptRegisterMethod = procedure (GDNativeHandle: Pointer; ClassName: PChar; FunctionName: PChar; 121 | Attributes: TGodotMethodAttributes; 122 | Method: TGodotInstanceMethod); cdecl; 123 | TGodotVariantNewNil = procedure (GodotVariant: PGodotVariant); cdecl; 124 | TGodotVariantNewInt = procedure (GodotVariant: PGodotVariant; Value: Int64); cdecl; 125 | 126 | // APIs: 127 | type 128 | PGodotGDNativeCoreApi = ^TGodotGDNativeCoreApi; 129 | TGodotGDNativeCoreApi = record 130 | ApiType: Cardinal; 131 | ApiVersion: TGodotGDNativeApiVersion; 132 | Next: PGodotGDNativeApiHeader; 133 | ExtensionCount: Cardinal; 134 | Extensions: PGDNativeApiExtensionArray; 135 | Functions1: Array[0..508] of Pointer; 136 | GodotVariantNewNil: TGodotVariantNewNil; 137 | GodotVariantNewBool: Pointer; 138 | GodotVariantNewUInt: Pointer; 139 | GodotVariantNewInt: TGodotVariantNewInt; 140 | Functions2: Array[0..230] of Pointer; 141 | end; 142 | PGodotGDNativeExtensionNativescriptApi = ^TGodotGDNativeExtensionNativescriptApi; 143 | TGodotGDNativeExtensionNativescriptApi = record 144 | ApiType: Cardinal; 145 | ApiVersion: TGodotGDNativeApiVersion; 146 | Next: PGodotGDNativeApiHeader; 147 | GodotNativescriptRegisterClass: TGodotNativescriptRegisterClass; 148 | FunctionToolClass: Pointer; 149 | GodotNativescriptRegisterMethod: TGodotNativescriptRegisterMethod; 150 | Functions: Array[0..2] of Pointer; 151 | end; 152 | 153 | procedure GodotApiExtraction (GodotGDNativeApiPointer: PGodotGDNativeCoreApi); 154 | 155 | var 156 | GodotGDNativeCoreApi: TGodotGDNativeCoreApi; 157 | GodotGDNativeExtensionNativescriptApi: TGodotGDNativeExtensionNativescriptApi; 158 | 159 | implementation 160 | 161 | procedure GodotApiExtraction (GodotGDNativeApiPointer: PGodotGDNativeCoreApi); 162 | var 163 | i: Integer; 164 | ExtensionArrayPointer: PGDNativeApiExtensionArray; 165 | ExtensionArray: TGDNativeApiExtensionArray; 166 | ExtensionPointer: PGodotGDNativeApiHeader; 167 | Extension: TGodotGDNativeApiHeader; 168 | begin 169 | GodotGDNativeCoreApi := GodotGDNativeApiPointer^; 170 | 171 | for i := 0 to GodotGDNativeCoreApi.ExtensionCount - 1 do 172 | begin 173 | ExtensionArrayPointer := GodotGDNativeCoreApi.Extensions; 174 | ExtensionArray := ExtensionArrayPointer^; 175 | 176 | ExtensionPointer := ExtensionArray[i]; 177 | Extension := ExtensionPointer^; 178 | 179 | if Extension.ApiType = GDNativeExtensionNativescript then 180 | begin 181 | GodotGDNativeExtensionNativescriptApi := PGodotGDNativeExtensionNativescriptApi(ExtensionPointer)^; 182 | end; 183 | end; 184 | end; 185 | 186 | end. -------------------------------------------------------------------------------- /godot/types/GodotArray.pas: -------------------------------------------------------------------------------- 1 | unit GodotArray; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | {$IFDEF FPC} 6 | {$PACKRECORDS C} 7 | {$ENDIF} 8 | 9 | interface 10 | 11 | const 12 | GodotArraySize = SizeOf(Pointer); 13 | 14 | type 15 | PGodotArray = ^TGodotArray; 16 | TGodotArray = record 17 | _dont_touch_that: Array[0..GodotArraySize-1] of Byte; 18 | end; 19 | 20 | implementation 21 | 22 | end. -------------------------------------------------------------------------------- /godot/types/GodotObject.pas: -------------------------------------------------------------------------------- 1 | unit GodotObject; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | {$IFDEF FPC} 6 | {$PACKRECORDS C} 7 | {$ENDIF} 8 | 9 | interface 10 | 11 | type 12 | PGodotObject = ^TGodotObject; 13 | TGodotObject = Pointer; 14 | 15 | implementation 16 | 17 | end. -------------------------------------------------------------------------------- /godot/types/GodotString.pas: -------------------------------------------------------------------------------- 1 | unit GodotString; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | {$IFDEF FPC} 6 | {$PACKRECORDS C} 7 | {$ENDIF} 8 | 9 | interface 10 | 11 | const 12 | GodotStringSize = SizeOf(Pointer); 13 | 14 | type 15 | PGodotString = ^TGodotString; 16 | TGodotString = record 17 | _dont_touch_that: Array[0..GodotStringSize-1] of Byte; 18 | end; 19 | 20 | implementation 21 | 22 | end. -------------------------------------------------------------------------------- /godot/types/GodotVariant.pas: -------------------------------------------------------------------------------- 1 | unit GodotVariant; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | {$IFDEF FPC} 6 | {$PACKRECORDS C} 7 | {$ENDIF} 8 | 9 | interface 10 | 11 | const 12 | GodotVariantSize = 16 + SizeOf(Pointer); 13 | 14 | type 15 | PPGodotVariant = ^PGodotVariant; 16 | PGodotVariant = ^TGodotVariant; 17 | TGodotVariant = record 18 | _dont_touch_that: Array[0..GodotVariantSize-1] of Byte; 19 | end; 20 | 21 | implementation 22 | 23 | end. --------------------------------------------------------------------------------