Okay, it's time to post some results, here.
First, I want to thank everyone who participated in this discussion, because for me this was a real learning experience.
I took to heart and mind every bit of input everyone had to contribute.
I knew what I wanted to do, I just didn't know how to go about doing it, successfully.
As I had illustrated previously, I did have a working model that just didn't fit most situations and it was mostly a hack anyway.
I downloaded the sources from the links provided by John, AIR and Peter.
I went through the documentation provided and studied the source code for each.
In all cases, a portion of the work of dynamically calling DLL functions at run-time is done using inline assembly language.
That is an important point to make note of.
The reason for that, is that at run-time, when calling a DLL function "on the fly", you have to bypass the regular system call and directly manipulate the STACK.
By that I mean you have to manually "PUSH" the parameters, that the function will be expecting, onto the stack before you call the DLL function.
Now with that said, the DLL tool I found to my likeing was Dyncall.
Not that there was anything wrong with the others, Dyncall just seemed more "turn-key", if you get my meaning.
Now, the documentation (if they had any) for all of these tools was among the worst.
I'm big on "good" documentation.
After exchanging a dozen or so emails with the developers of Dyncall, I finally got it working.
Unfortunately, their lengthy documentation doesn't actually show you how to use it.
It spends more time on describing all the systems they have tested it on and technical info about the build process.
Anyway...,
I have an example here that illustrates, using C source code, just how simple Dyncall makes the process of calling DLL functions:
/* This routine dynamically calls MessageBox */
/* (or any API function) at run-time. */
/* LINK with these LIBs: libdyncall_s.lib, libdynload_s.lib */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dyncall.h>
#include <dynload.h>
char dllname[32];
char functionname[32];
int main()
{ int xhwnd = 0, xtype = 1, retVal;
char text[20] = {"hello world"};
char capt[10] = {"hello"};
void* funcptr;
void* libhandle;
/* name of DLL to open */
strcpy(dllname, "user32.dll");
/* name of function to call */
strcpy(functionname, "MessageBoxA");
/* open DLL */
libhandle = dlLoadLibrary(dllname);
/* here: check for NULL return: failure */
/* locate function */
funcptr = dlFindSymbol(libhandle,functionname);
/* here: check for NULL return: failure */
/* create a callvm (to be shared within your app) */
DCCallVM * pvm = dcNewCallVM(4096);
/* configure the callvm for call conv..*/
dcMode(pvm, DC_CALL_C_X86_WIN32_STD);
/* reset the argument buffer */
dcReset(pvm);
/* now load arguments (from left to right order) */
dcArgInt(pvm, xhwnd);
dcArgPointer(pvm, text);
dcArgPointer(pvm, capt);
dcArgInt(pvm, xtype);
/* now call by specifying return type */
retVal = dcCallInt(pvm,funcptr);
/* free library handle */
dlFreeLibrary(libhandle);
/* free VM */
dcFree(pvm);
system("pause");
return 0;
}
/*--------- end main ----------*/
I have attached a Windows executable, called shelldcall.zip for the above code.
Now, that's not the end of it.
I have done a considerable amount of experimentation on my own, as well.
I first experimented using Masm, doing the whole thing in straight assembly language and it worked quite well.
And, much to my surprise, was quite simple to accomplish.
But, since Bxbasic is written in C, using the LccWin32 compiler, I wanted to be able to do this using "inline" assembly language.
For those not familiar with the concept, "inline assembly" is assembly language embeded into the C source code and compiled with the main program.
To illustrate this, I have as an example, the exact same program as the above, written in C, using "inline assembly":
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
void * (__stdcall *stdcall_func)();
char dllname[20]="user32.dll";
char functionname[20]="MessageBoxA";
HWND hwnd=0;
UINT utype=1;
char text[] = "Hello Windows!";
char strng[] = "Winasm";
HMODULE hLib=0;
int main()
{
_asm("pushl $_dllname");
_asm("call %LoadLibraryA");
_asm("movl %eax, _hLib");
_asm("pushl $_functionname");
_asm("pushl %hLib");
_asm("call %GetProcAddress");
_asm("movl %eax, _stdcall_func");
_asm("pushl _utype");
_asm("pushl $_strng");
_asm("pushl $_text");
_asm("pushl _hwnd");
_asm("call *_stdcall_func");
FreeLibrary(hLib);
system("pause");
return 0;
}
/*--------- end main ----------*/
Sweet !
I have attached a Windows executable, called shellacall.zip for the above code.
I presently have Bxbasic setup for Dyncall and have been testing it and it works quite well.
Shortly, I will fully develop my own inline version and will replace Dyncall with it.
If anyone has any questions, I will be only too happy to answer them.
I couldn't have done this without your help.
Thanks
Steve