Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DLL Talk / Complete Guide to TPCs written in Delphi

Author
Message
empty
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: 3 boats down from the candy
Posted: 11th Jan 2006 01:16
Note:
I started this a while ago and never really found the time to finished it. That means it might contain errors and typos of
all sorts, and all code examples provided are not tested but should theoretically work . If you find any issues please report.



This tutorial will show how to create simple Third Party Plugins for DarkBasic Pro in Delphi. Simple means that it will only explain how to pass or return all possible data types to/from the DLL. It will not cover how to manipulate objects, meshes, or other data in DBpro apps. Even though it's entirely possible it would also require to update the GlobStruct header translation to upgrade 5.9 changes, and I simply don't have time for that.

If someone else is interested in updating the header translation, you can find my old version here in case you want to use it as a starting point.


Topics:
1. Creating a DLL in Delphi
2. A generic DLL Framework for TPCs
3. Passing and Returning Values
4. String Tables Part I
5. String Tables Part II
6. A little Example
7. Returning Floats and Strings








1. Creating a DLL in Delphi

In order to create a Dll do the following
- Click on "File" -> "New" -> "Other"
- In the "New Items" dialog select "DLL Wizard" and click "OK"
This will generate a code that looks like this: (bare the comments):



Now we can fine tune this code to our specific needs and create a reuseable framework


Play Nice! Play Basic! Version 1.089
empty
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: 3 boats down from the candy
Posted: 11th Jan 2006 01:16 Edited at: 11th Jan 2006 01:18
2. A generic DLL Framework for TPCs

When we take a look at the USES clause we will notice that Delphi automatically includes the libraries "SysUtils" and "Classes". They will increase the DLL file size and since we don't don't whether we'll need them at this point, we can remove both of them. Instead we include the windows library. At this point we can get rid of the resource file {$R *.res} too. We'll get back to resource files later on:


As soon as a DBPro application executes, it will call two functions from each DLL it uses. The first one is called "Constructor" (decorated name: ?Constructor@@YAXXZ). This is a good place to reserve or allocate memory for example. We don't need it for our examples in this tutorial, but we'll add this to our framework:


The keyword "cdecl" at defines the calling convention. There are several others (stdcall, pascal, register) but cdecl is what DarkBasic Pro needs. To make sure DarkBasic Pro (or any program other program) can access this function we need to "export" it. For that we'll add:


"Construct" is the name of our function/procedure followed by the keyword "name" that indicates that the function/procedure is exported with a different name. "?Constructor@@YAXXZ" is what DarkBasic Pro will call. In other words when "?Constructor@@YAXXZ" is called it will be 're-directed' to "Construct".

After "Constructor" DarkBasic Pro will call ReceiveCoreDataPtr (decorated name: ?ReceiveCoreDataPtr@@YAXPAX@Z). It will pass a pointer to a structure (Type) called GlobStruct that contains one address to a function (or actually procedure) in DarkBasic Pro that we need for string handling. This procedure has the following form:
procedure CreateDeleteString(OldString, NewStrLen: DWORD); cdecl;
Its address is stored in the first field of the structure, so we will calculate that one within the ReceiveCoreDataPtr procedure and store it in a global variable.


Finally, before a DarkBasic Pro application ends it calls "Destructor" (decorated name: ?Destructor@@YAXXZ).


So the complete code look like this now:


We can add this framework to our Repository ("Project" -> "Add to Repository..."). That way we can access it through "File" -> "New" -> "Other", or we just save it somewhere and load it each time we are going to write a TPC DLL.


Play Nice! Play Basic! Version 1.089
empty
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: 3 boats down from the candy
Posted: 11th Jan 2006 01:19
3. Passing and Returning Values

The first column of following table lists the nine basic data types that DarkBasic Pro knows. The second column contains the according Delphi types when we pass them to TPC functions:


For example we want to pass an Integer variable called "myInt", a String variable called "myString" and a Boolean variable called "myBool" to a TPC. In Delphi the procedure would look like this:


Another example where we pass a Double Float a Double Integer and a Byte variable:


Passing values to a TPC is pretty straight forward. Returning is almost equally simple and we can use the above table to determine the nessecary Delphi types too. However there are too exceptions: When we are going to return String (PChar) or Float (Single) values we need a different approach. We will talk about that later.


Play Nice! Play Basic! Version 1.089
empty
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: 3 boats down from the candy
Posted: 11th Jan 2006 01:21
4. String Tables Part I

String tables are used to tell DBpro what function or procedure a command is assigned to. I'll use the example of the DarkBasic Pro Help files to explain how the entries in the string table look like:
PRINT TEXT%S%?PrintText@@YAXPAD@Z%String
An entry has three parts separated by a percentage symbol (%)
PRINT TEXT: the name of the command that we can use in DarkBasic Pro.
S: type of the parameter- String in this case (see table below)
PrintText@@YAXPAD@Z: the name of the DLL function assigned to the command (those will look different in Delphi).
String: a description of the parameter in plain English (optional).

If a command returns a value (which is called expression) the takes an additional symbol. namely a square bracket ([). It is placed directly after the command name before the first separator:
GET VALUE[%L%?GetValue@@YAHXZ
In this case the first character after the first separator specifies the return type of the expression (in this case integer). That also means that this example takes no parameters and would be called like this: Value = Get Value() in DarkBasic Pro.

This list shows what character are used to define the parameter and return types:
L = Integer
F = Float
S = String
O = Double Float (capital o)
R = Double Integer (capital r)
D = Boolean, BYTE, WORD and DWORD
0 = Zero Character (no param)

If we want to make a command called "SHOW MESSAGE" that takes a String parameter (the message) and a Boolean parameter (False means OK button, True means OK & Cancel Button), we would write the following String Table:
SHOW MESSAGE%SD%ShowMessageFunc
where ShowMessageFunc is the name of our Delphi procedure.

Now this wouldn't make a lot sense, as we must find out which of the two buttons were clicked, therefore our Delphi function will return a DWord containing either 0 or 1. We need to change the String Table entry to this:
SHOW MESSAGE[%DSD%ShowMessageFunc




5. String Tables Part II

Now we know how to write String Table entries, but how do we get them compiled into our DLL? String Tables are part of resource files which can be linked to EXE or DLL files. In Delphi it's a little more complicated than in Visual C++ unless we have a third party resource editor. We will use the manual approach here.
First we need to create a plain text file that containes our String Table entries. In the Delphi IDE Click on "File" -> "New" -> "Other", select "Text File" and click "OK". We will add two example entries to
demonstrate how a String Table resource file might look:


Save this file as cmdtable.rc in the folder where your Delphi project is stored. Now we need to execute the resource compiler which is a command line tool. Click the Windows "Start" button then choose "Run" and type "Command" in Windows 98 and Me or "cmd" in 2000 and XP and press "<Enter>". Now enter the path the folder where you stored the cmdtable.rc file in and press enter. To execute the resource compiler type: "BRC32.exe -r cmdtable.rc" and press "<Enter>". This will generate a file "cmdtable.res" that we need to link to our Delphi project by adding the line
{$R cmdtable.res}
after the USES clause.


Play Nice! Play Basic! Version 1.089
empty
22
Years of Service
User Offline
Joined: 26th Aug 2002
Location: 3 boats down from the candy
Posted: 11th Jan 2006 01:23
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:


Now we need to add that function to the "exports" section:


Create and compile the string table (cmdtable.rc):


Add {$R cmdtable.res} after the USES clause and that's it.

Complete code:





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:



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:


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:


With this string table


We can call it in DBPro this way:


Output:
Hello, World


Play Nice! Play Basic! Version 1.089
hyrichter
20
Years of Service
User Offline
Joined: 15th Feb 2004
Location: Arizona
Posted: 17th Jan 2006 01:51
Excellent, excellent. Now it makes much more sense to me.

Login to post a reply

Server time is: 2024-11-21 23:43:09
Your offset time is: 2024-11-21 23:43:09