6. A little Example
Now that we know the basics we are going to create our first few examples. We'll start with a simple Min function that will receive two integer values and return the smallest of them. Load our TPC framework and add the following function:
function CalcMin(Value1, Value2: LongInt): LongInt; cdecl;
begin
result := Value1;
if Value1 > Value2 then result := Value2;
end;
Now we need to add that function to the "exports" section:
exports
Construct name '?Constructor@@YAXXZ',
Destruct name '?Destructor@@YAXXZ',
ReceiveCoreDataPtr name '?ReceiveCoreDataPtr@@YAXPAX@Z',
CalcMin;
Create and compile the string table (cmdtable.rc):
STRINGTABLE
Begin
1, "MIN[%LLL%CalcMin"
End
Add {$R cmdtable.res} after the USES clause and that's it.
Complete code:
library Project1;
uses
Windows;
{$R cmdtable.res}
// String handling function pointer
var CreateDeleteString: procedure(OldString, NewStrLen: DWORD); cdecl;
// Called by DBPro immediately after loading the DLL
procedure Construct; cdecl;
begin
end;
// Called by DBPro after Construct
procedure ReceiveCoreDataPtr(GlobCorePtr : Pointer); cdecl;
begin
@CreateDeleteString := Pointer(GlobCorePtr^);
end;
// Called by DBPro before termination
procedure Destruct; cdecl;
begin
end;
function CalcMin(Value1, Value2: LongInt): LongInt; cdecl;
begin
result := Value1;
if Value1 > Value2 then result := Value2;
end;
exports
Construct name '?Constructor@@YAXXZ',
Destruct name '?Destructor@@YAXXZ',
ReceiveCoreDataPtr name '?ReceiveCoreDataPtr@@YAXPAX@Z',
CalcMin;
begin
end.
7. Returning Floats and Strings
We already know that returning Floats and Strings is not as straight forward as returning other types.
7.1. Floats
Floats are returned in a DWord; that means we must copy the float value to the address of the DWord we're going to return.
This example function does just this:
function ReturnAFloat; DWord; cdecl;
var fValue: Single;
begin
fValue := 42.05;
CopyMemory(@Result, @fValue, 4);
end;
7.2. Strings
When we want to return a string value from our TPC, DarkBasic Pro will pass the address of an old string (or nil) as the first parameter. Now we need to call the function "CreateDeleteString" (see Topic 2.) with the NewStrLen of 0. This will delete the string. Then we can create a new string by calling the same function with the length of our string. Here's an example function:
function ReturnHello(oldString: PChar): PChar; cdecl;
var tmp: PChar;
begin
if oldString <> nil then CreateDeleteString(oldString, 0);
tmp := 'Hello';
CreateDeleteString(result, 5+1); //length of "Hello" + 1
StrCopy(result, tmp)
end;
This function has no arguments and returns the String "Hello".
If we have a string type variable that we want to return from our function, we can use this method:
function ReturnString(oldString, StringIn: PChar): PChar; cdecl;
var tmp: String;
begin
if oldString <> nil then CreateDeleteString(oldString, 0);
tmp := 'Hello, ' + StringIn;
CreateDeleteString(result, 5+1); //length of "Hello" + 1
StrCopy(result, PChar(tmp))
end;
With this string table
STRINGTABLE
Begin
1, "HELLO[%SS%ReturnString"
End
We can call it in DBPro this way:
A$ = HELLO("World")
PRINT A$
Output:
Hello, World