Post by Nicky Peter Hollyoake on Oct 23, 2008 15:11:22 GMT -5
Ok, peoples always asking how to make a .DLL. I'll give them a quick step-by-step on how to do that we'll make the "square root" function again.
First download code::blocks.
Next download the plugin SDK from the Basic4GL website & save it anywhere you want.
Next open up code::blocks, and then open up "PluginDLLMain.CPP" from the SDK.
Next open up "PluginDLL.CBP" from the SDK aswell.
Now heres the code that should be there ...
Ok where we make a codes is here ...
So we gonna add our own one, below that last part put this ...
See how I named it "Func_SquareRoot" you can name that anything you like.
Next at the top of the program where this is ...
Add ...
at the bottom of "#include <windows.h>". We're adding this so we got math functions.
Now go back to the "Func_SquareRoot" part.
Put ...
Now here this reads a parameter of the command when our functions complete it will be this in Basic4GL.
So what "basic4gl.GetFloatParam" is reading the parameter as a float and the "1" is telling it what paremeter, by the way it goes right to left so parameter "1" would start from the right and go left from there on parameter 2. In our case we only got one parameter so it doesn't matter just read the first parameter but in cases like ...
We'll go "basic4gl.GetFloatParam(1)" for the second parameter, and "basic4gl.GetFloatParam(2)" for the 1 parameter. We also got "GetStringParam", and "GetIntParam" if the parameter is a different type we reading. Anyways back to the code. Lets add ...
Know how in Basic4GL user-defined functions you put "return 1", etc. Well thats exectly what "basic4gl.SetFloatReturn(float)", it returns the float number back to Basic4GL. We can use "sqrt" because we added the maths library & when we caculate that we return it back to Basic4GL. Once again you also got "basic4gl.SetIntReturn" to return integers and you also got string.
After all that we completed the main part of the function ...
Now you can make more of these. Just name them different stuff (eg: "Func_Add"). Now lets register the command, where these are ...
At the bottom of it put ...
registry.RegisterFunction creates the function, the firsrt parameter isyour function name, the second parameter we put the "Func_Squareroot" whatever you named it, and the first parameter what our return type is and thats a float, we also got 'DLL_BASIC4GL_INT', 'DLL_BASIC4GL_STRING'. Now registry.AddParam adds a parameter to your command and you have to tell it what the parameter can hold a string, float, or int. And there you have it, a perfect code!
By the way, if you wanna create a constants just add it where all the other registry is the functions are ...
The first is what the constant is called, and the number is what it holds. Theres also string & int. Theres alot more, but hopefully now we got the basics over with you'll easily pick them up.
- Nicky
P. S. Forgot to say to create the plugin go to "Build > Build" and it should be in the bin folder in your SDK folder. ;D
Full source
First download code::blocks.
Next download the plugin SDK from the Basic4GL website & save it anywhere you want.
Next open up code::blocks, and then open up "PluginDLLMain.CPP" from the SDK.
Next open up "PluginDLL.CBP" from the SDK aswell.
Now heres the code that should be there ...
/* Example DLL project.
Created by: Thomas Mulgrew (tmulgrew@slingshot.co.nz)
This project will build a simple DLL that can be plugged into Basic4GL.
It contains one library function for example purposes.
I recommend using this as a template for creating Basic4GL plugin DLLs.
*/
///////////////////////////////////////////////////////////////////////////////
// Includes
// At the very least, Basic4GLDLLInterface.h must be included.
// Add any other include files here.
#include "Basic4GLDLLInterface.h"
// This example uses the windows MessageBox function, so we include the windows
// header.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
///////////////////////////////////////////////////////////////////////////////
// Constants
//
// Update these to describe your DLL.
const char *DESCRIPTION = "[Enter description of DLL here]"; // This is displayed in the "Plug-in Chooser" in Basic4GL
const int VERSION_MAJOR = 1; // Major version number
const int VERSION_MINOR = 0; // Minor version number
///////////////////////////////////////////////////////////////////////////////
// Plugin
//
/// Main object representing the plugin to Basic4GL.
/// Basic4GL will access this through the IDLL_Plugin interface.
class Plugin : public IDLL_Basic4GL_Plugin {
public:
Plugin() { ; }
virtual bool DLLFUNC Load(IDLL_Basic4GL_FunctionRegistry ®istry, bool isStandaloneExe);
virtual bool DLLFUNC Start();
virtual void DLLFUNC End();
virtual void DLLFUNC Unload();
virtual void DLLFUNC GetError(char *error);
virtual void DLLFUNC Pause();
virtual void DLLFUNC Resume();
virtual void DLLFUNC DelayedResume();
virtual void DLLFUNC ProcessMessages();
};
///////////////////////////////////////////////////////////////////////////////
// DLL exported functions
extern "C" {
/// Query function
DLLExport int DLLFUNC Basic4GL_Query(char *details, int *major, int *minor) {
int i;
for (i = 0; DESCRIPTION[i] != 0; i++)
details[i] = DESCRIPTION[i];
*major = VERSION_MAJOR;
*minor = VERSION_MINOR;
return BASIC4GL_DLL_VERSION;
}
/// Main initialisation function.
/// Here we will construct and return our plugin object
DLLExport IDLL_Basic4GL_Plugin *DLLFUNC Basic4GL_Init() {
// Construct and return our plugin object
return new Plugin();
}
}
///////////////////////////////////////////////////////////////////////////////
// Runtime functions
// These are the functions that Basic4GL calls
/// Display a messagebox
void DLLFUNC Func_Max(IDLL_Basic4GL_Runtime &basic4gl) {
// Extract parameters
float firstValue = basic4gl.GetFloatParam(2);
float secondValue = basic4gl.GetFloatParam(1);
// Calculate maximum
float maximum;
if (firstValue > secondValue)
maximum = firstValue;
else
maximum = secondValue;
// Return value to Basic4GL
basic4gl.SetFloatResult(maximum);
}
void DLLFUNC Func_MessageBox(IDLL_Basic4GL_Runtime &basic4gl) {
// Extract string parameter
const char *msg = basic4gl.GetStringParam(1);
// Display the message box
MessageBox(NULL, msg, "Plugin DLL", MB_OK);
}
///////////////////////////////////////////////////////////////////////////////
// Plugin
bool DLLFUNC Plugin::Load(IDLL_Basic4GL_FunctionRegistry ®istry, bool isStandaloneExe) {
// Initialise DLL stuff
// Register shared interfaces
// Register runtime functions
// Max function
registry.RegisterFunction("Max", Func_Max, DLL_BASIC4GL_FLOAT); // Function "max" returns a float (floating point number)
registry.AddParam(DLL_BASIC4GL_FLOAT); // First parameter is a float
registry.AddParam(DLL_BASIC4GL_FLOAT); // Second parameter is a float
// Message box function
registry.RegisterVoidFunction("MessageBox", Func_MessageBox);
registry.ModTimeshare(); // This function is slow, so Basic4GL better perform a timeshare break after it finishes
registry.AddParam(DLL_BASIC4GL_STRING);
return true;
}
void DLLFUNC Plugin::Unload() {
// DLL is about to unload.
// Any final cleanup code (closing files, releasing resources etc) would go here
// Delete this object. This is safe because Basic4GL will not access it again.
delete this;
}
bool DLLFUNC Plugin::Start() {
// Program is about to start.
// Any pre-start init code would go here.
return true;
}
void DLLFUNC Plugin::End() {
// Program is about to end
// Any cleanup code would go here
}
void DLLFUNC Plugin::Pause() {
// Called when the program is paused (i.e. during debugging).
// A full screen window might hide itself here so that the user can see the
// Basic4GL edit window (and debug their program)
}
void DLLFUNC Plugin::Resume() {
// Called when the program is resumed (i.e. during debugging).
// This is also called when the user "steps"
}
void DLLFUNC Plugin::DelayedResume() {
// Called when the program is resumed for more than a short "step".
// This is where a fullscreen window would re-show itself (if it did so in ::Resume()
// we would get flickering when the user steps through the program)
}
void DLLFUNC Plugin::GetError(char *error) {
// We don't return errors, but if we did, we would strcpy them to *error here.
;
}
void DLLFUNC Plugin::ProcessMessages() {
// Called periodically (in practice, quite frequently).
// This would be a good place to process windows messages etc.
}
Ok where we make a codes is here ...
/// Display a messagebox
void DLLFUNC Func_Max(IDLL_Basic4GL_Runtime &basic4gl) {
// Extract parameters
float firstValue = basic4gl.GetFloatParam(2);
float secondValue = basic4gl.GetFloatParam(1);
// Calculate maximum
float maximum;
if (firstValue > secondValue)
maximum = firstValue;
else
maximum = secondValue;
// Return value to Basic4GL
basic4gl.SetFloatResult(maximum);
}
void DLLFUNC Func_MessageBox(IDLL_Basic4GL_Runtime &basic4gl) {
// Extract string parameter
const char *msg = basic4gl.GetStringParam(1);
// Display the message box
MessageBox(NULL, msg, "Plugin DLL", MB_OK);
}
So we gonna add our own one, below that last part put this ...
void DLLFUNC Func_SquareRoot(IDLL_Basic4GL_Runtime &basic4gl) {
}
See how I named it "Func_SquareRoot" you can name that anything you like.
Next at the top of the program where this is ...
// This example uses the windows MessageBox function, so we include the windows
// header.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
Add ...
#include <cmath>
at the bottom of "#include <windows.h>". We're adding this so we got math functions.
Now go back to the "Func_SquareRoot" part.
Put ...
float Number = basic4gl.GetFloatParam(1);
Now here this reads a parameter of the command when our functions complete it will be this in Basic4GL.
Printr SqrRoot(9)
So what "basic4gl.GetFloatParam" is reading the parameter as a float and the "1" is telling it what paremeter, by the way it goes right to left so parameter "1" would start from the right and go left from there on parameter 2. In our case we only got one parameter so it doesn't matter just read the first parameter but in cases like ...
Pow(1, 2)
We'll go "basic4gl.GetFloatParam(1)" for the second parameter, and "basic4gl.GetFloatParam(2)" for the 1 parameter. We also got "GetStringParam", and "GetIntParam" if the parameter is a different type we reading. Anyways back to the code. Lets add ...
float SqrN = sqrt(Number);
basic4gl.SetFloatResult(SqrN);
Know how in Basic4GL user-defined functions you put "return 1", etc. Well thats exectly what "basic4gl.SetFloatReturn(float)", it returns the float number back to Basic4GL. We can use "sqrt" because we added the maths library & when we caculate that we return it back to Basic4GL. Once again you also got "basic4gl.SetIntReturn" to return integers and you also got string.
After all that we completed the main part of the function ...
void DLLFUNC Func_SquareRoot(IDLL_Basic4GL_Runtime &basic4gl) {
float Number = basic4gl.GetFloatParam(1);
float SqrN = sqrt(Number);
basic4gl.SetFloatResult(SqrN);
}
Now you can make more of these. Just name them different stuff (eg: "Func_Add"). Now lets register the command, where these are ...
// Max function
registry.RegisterFunction("Max", Func_Max, DLL_BASIC4GL_FLOAT); // Function "max" returns a float (floating point number)
registry.AddParam(DLL_BASIC4GL_FLOAT); // First parameter is a float
registry.AddParam(DLL_BASIC4GL_FLOAT); // Second parameter is a float
// Message box function
registry.RegisterVoidFunction("MessageBox", Func_MessageBox);
registry.ModTimeshare(); // This function is slow, so Basic4GL better perform a timeshare break after it finishes
registry.AddParam(DLL_BASIC4GL_STRING);
At the bottom of it put ...
registry.RegisterFunction ("SquareRoot", Func_SquareRoot, DLL_BASIC4GL_FLOAT);
registry.AddParam(DLL_BASIC4GL_FLOAT);
registry.RegisterFunction creates the function, the firsrt parameter isyour function name, the second parameter we put the "Func_Squareroot" whatever you named it, and the first parameter what our return type is and thats a float, we also got 'DLL_BASIC4GL_INT', 'DLL_BASIC4GL_STRING'. Now registry.AddParam adds a parameter to your command and you have to tell it what the parameter can hold a string, float, or int. And there you have it, a perfect code!
By the way, if you wanna create a constants just add it where all the other registry is the functions are ...
registry.RegisterFloatConstant("RND_M", 32767);
The first is what the constant is called, and the number is what it holds. Theres also string & int. Theres alot more, but hopefully now we got the basics over with you'll easily pick them up.

- Nicky
P. S. Forgot to say to create the plugin go to "Build > Build" and it should be in the bin folder in your SDK folder. ;D
Full source
/* Example DLL project.
Created by: Thomas Mulgrew (tmulgrew@slingshot.co.nz)
This project will build a simple DLL that can be plugged into Basic4GL.
It contains one library function for example purposes.
I recommend using this as a template for creating Basic4GL plugin DLLs.
*/
///////////////////////////////////////////////////////////////////////////////
// Includes
// At the very least, Basic4GLDLLInterface.h must be included.
// Add any other include files here.
#include "Basic4GLDLLInterface.h"
// This example uses the windows MessageBox function, so we include the windows
// header.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cmath>
///////////////////////////////////////////////////////////////////////////////
// Constants
//
// Update these to describe your DLL.
const char *DESCRIPTION = "[Enter description of DLL here]"; // This is displayed in the "Plug-in Chooser" in Basic4GL
const int VERSION_MAJOR = 1; // Major version number
const int VERSION_MINOR = 0; // Minor version number
///////////////////////////////////////////////////////////////////////////////
// Plugin
//
/// Main object representing the plugin to Basic4GL.
/// Basic4GL will access this through the IDLL_Plugin interface.
class Plugin : public IDLL_Basic4GL_Plugin {
public:
Plugin() { ; }
virtual bool DLLFUNC Load(IDLL_Basic4GL_FunctionRegistry ®istry, bool isStandaloneExe);
virtual bool DLLFUNC Start();
virtual void DLLFUNC End();
virtual void DLLFUNC Unload();
virtual void DLLFUNC GetError(char *error);
virtual void DLLFUNC Pause();
virtual void DLLFUNC Resume();
virtual void DLLFUNC DelayedResume();
virtual void DLLFUNC ProcessMessages();
};
///////////////////////////////////////////////////////////////////////////////
// DLL exported functions
extern "C" {
/// Query function
DLLExport int DLLFUNC Basic4GL_Query(char *details, int *major, int *minor) {
int i;
for (i = 0; DESCRIPTION[i] != 0; i++)
details[i] = DESCRIPTION[i];
*major = VERSION_MAJOR;
*minor = VERSION_MINOR;
return BASIC4GL_DLL_VERSION;
}
/// Main initialisation function.
/// Here we will construct and return our plugin object
DLLExport IDLL_Basic4GL_Plugin *DLLFUNC Basic4GL_Init() {
// Construct and return our plugin object
return new Plugin();
}
}
///////////////////////////////////////////////////////////////////////////////
// Runtime functions
// These are the functions that Basic4GL calls
/// Display a messagebox
void DLLFUNC Func_Max(IDLL_Basic4GL_Runtime &basic4gl) {
// Extract parameters
float firstValue = basic4gl.GetFloatParam(2);
float secondValue = basic4gl.GetFloatParam(1);
// Calculate maximum
float maximum;
if (firstValue > secondValue)
maximum = firstValue;
else
maximum = secondValue;
// Return value to Basic4GL
basic4gl.SetFloatResult(maximum);
}
void DLLFUNC Func_MessageBox(IDLL_Basic4GL_Runtime &basic4gl) {
// Extract string parameter
const char *msg = basic4gl.GetStringParam(1);
// Display the message box
MessageBox(NULL, msg, "Plugin DLL", MB_OK);
}
void DLLFUNC Func_SquareRoot(IDLL_Basic4GL_Runtime &basic4gl) {
float Number = basic4gl.GetFloatParam(1);
float SqrN = sqrt(Number);
basic4gl.SetFloatResult(SqrN);
}
///////////////////////////////////////////////////////////////////////////////
// Plugin
bool DLLFUNC Plugin::Load(IDLL_Basic4GL_FunctionRegistry ®istry, bool isStandaloneExe) {
// Initialise DLL stuff
// Register shared interfaces
// Register runtime functions
// Max function
registry.RegisterFunction("Max", Func_Max, DLL_BASIC4GL_FLOAT); // Function "max" returns a float (floating point number)
registry.AddParam(DLL_BASIC4GL_FLOAT); // First parameter is a float
registry.AddParam(DLL_BASIC4GL_FLOAT); // Second parameter is a float
// Message box function
registry.RegisterVoidFunction("MessageBox", Func_MessageBox);
registry.ModTimeshare(); // This function is slow, so Basic4GL better perform a timeshare break after it finishes
registry.AddParam(DLL_BASIC4GL_STRING);
registry.RegisterFunction ("SquareRoot", Func_SquareRoot, DLL_BASIC4GL_FLOAT);
registry.AddParam(DLL_BASIC4GL_FLOAT);
registry.RegisterFloatConstant("RND_M", 32767);
return true;
}
void DLLFUNC Plugin::Unload() {
// DLL is about to unload.
// Any final cleanup code (closing files, releasing resources etc) would go here
// Delete this object. This is safe because Basic4GL will not access it again.
delete this;
}
bool DLLFUNC Plugin::Start() {
// Program is about to start.
// Any pre-start init code would go here.
return true;
}
void DLLFUNC Plugin::End() {
// Program is about to end
// Any cleanup code would go here
}
void DLLFUNC Plugin::Pause() {
// Called when the program is paused (i.e. during debugging).
// A full screen window might hide itself here so that the user can see the
// Basic4GL edit window (and debug their program)
}
void DLLFUNC Plugin::Resume() {
// Called when the program is resumed (i.e. during debugging).
// This is also called when the user "steps"
}
void DLLFUNC Plugin::DelayedResume() {
// Called when the program is resumed for more than a short "step".
// This is where a fullscreen window would re-show itself (if it did so in ::Resume()
// we would get flickering when the user steps through the program)
}
void DLLFUNC Plugin::GetError(char *error) {
// We don't return errors, but if we did, we would strcpy them to *error here.
;
}
void DLLFUNC Plugin::ProcessMessages() {
// Called periodically (in practice, quite frequently).
// This would be a good place to process windows messages etc.
}