The tutorial will assume that you are writing a dll that will be used with Liberty BASIC and that you are familiar with calling dlls from LB. It also assumes that you are at least a little familiar with the Windows API.
BOOL WINAPI __declspec(dllexport) LibMain (HINSTANCE hInst, DWORD Reason, LPVOID Reserved)
{
if(Reason==DLL_PROCESS_ATTACH)
{
return TRUE;
}
if(Reason==DLL_PROCESS_DETACH)
{
return TRUE;
}
return FALSE;
}
In some cases you may need to perform some sort of initialiazation for your dll when it is first loaded, perhaps setting some array elements to a certain value or setting aside some memory. The place to do this is in this section of the entry point function:
if(Reason==DLL_PROCESS_ATTACH)
{
// Perform your initialization here.
return TRUE;
}
If your initializing code fails for any reason, like trying to allocate some memory and the computer doesn't have enough memory available, then you should return FALSE instead of TRUE. If FALSE is returned the dll will not be loaded.This is the place to do any cleanup that may be required when your dll is closed:
if(Reason==DLL_PROCESS_DETACH)
{
// Perform your cleanup here.
return TRUE;
}
INT __declspec(dllexport) __stdcall Addit ( int A, int B)
{
int C;
C = A + B;
return C;
}
Let's break down this function and examine it.
INT means that this function will return an integer,
These next two items are preceeded by a double underscore.
__declspec(dllexport) means that this function is to be called from an external program,
__stdcall identifies the calling convention used,
Addit is the name of this function,
and ( int A, int B) means that there must be two integers, A and B, passed to this function when it is called. When you call this function, the two integers can have any name at all in the calling program.
{
// declare a local integer variable.
int C;
C = A + B;
// return the value of C to the calling program.
return C;
}
The function takes 4 parameters.
LONG __declspec(dllexport) __stdcall ChangeWinTxt ( HWND hWin, CHAR *sztxt, LONG numChars, CHAR *szret )
{
// declare a local string array to hold up to 2048 characters of text
char szWinTxt [2048];
// declare a local variable of type long
long lRet;
if(strcmp(sztxt,"")==0)
{
return 0; // and exit this function
}
// retrieve up to numChars of text from the window
GetWindowText ( hWin, (LPTSTR) szWinTxt, numChars );
// set the new window text
lRet = SetWindowText ( hWin, sztxt );
// return the previous window text by copying it to
// the string in LB that is pointed to by szret
sprintf ( szret, "%s", szWinTxt );
// return will be 0 if SetWindowText failed or >0 if success.
return lRet;
}
This function could also be written with only one pointer to a string and that string could be used as both a variable containing the new text and the variable that will have the old text returned to it.
LONG __declspec(dllexport) __stdcall ChangeWinTxtA ( HWND hWin, CHAR *sztxt, LONG numChars )
{
char szWinTxt [2048];
long lRet;
if(strcmp(sztxt,"")==0)
{
return 0;
}
GetWindowText ( hWin, (LPTSTR) szWinTxt, numChars );
lRet = SetWindowText ( hWin, sztxt );
sprintf ( sztxt, "%s", szWinTxt );
return lRet;
}
struct MyStruct
{
long NumA;
long NumB;
long NumC;
}; // notice the semicolon here
Now we can write a function that takes a pointer - named strct - to a structure. The structure that strct points to must be defined in your Liberty BASIC program and must be constructed with the same type and number of elements as our dll structure that we named MyStruct.
VOID __declspec(dllexport) __stdcall FillStruct (struct MyStruct *strct )
{
// copy some values to the structure that is in the LB program
strct->NumA = 100;
strct->NumB = 200;
strct->NumC = 300;
}
The structure you define in your LB program does not have to be named "MyStruct" and its elements do not have to be named NumA etc. It only needs to have the same type and number of elements, in the same order, as the structure in your dll. You are not required to return values to all of the elements in the calling program's structure, or even any values. If you don't return a value to a structure element then that element simply retains the value it had before the dll function was called.
You also have the option of setting the values of the structure in your LB program, calling the dll function with a pointer to that structure, using some or all of the values of the structure as parameters and optionally returning new values to that same structure.
You may have noticed that the last function didn't have a "return" statement. That's because it was declared with VOID. It could have been declared as INT or LONG etc. and a return statement used to return some value. VOID was used just to illustrate that the dll function itself does not have to return a value.
Demo files for the above examples Download