Home page Home page Home page Home page
Pixel
Pixel Header R1 C1 Pixel
Pixel Header R2 C1 Pixel
Pixel Header R3 C1 Pixel
Pixel
By Captain C | Wednesday 17 June 2009 12:13 | 0 Comments
As you probably know DLL prototyping with OpenInsight is the process of defining functions exported from a Windows DLL so that they may be called from your Basic+ programs.

In a nutshell the process involves creating a "prototype record" in your SYSPROCS table containing a list of all the functions in the DLL you wish to use along with the type of arguments each function expects. After that you run a system process called Declare_Fcns() which uses the prototype record to create one or more "DLL stub programs" in your SYSOBJ table. These programs have a special format that, when executed, tells OpenEngine that it should load and call a function in a DLL rather than trying to execute it as a "normal" program.

(The entire process is described in detail in Chapter 7 of the Programmers Reference Manual on-line help)

When creating the prototype record there are several conventions that the product documentation follows that can lead to problems over time, and in this post we'll have a look at how to avoid them using the concept of "namespaces" - i.e. making sure that any naming conventions you use during the prototyping process are unique to your application so you avoid collisions with other objects in the system.


Naming the prototype record

The first issue is with the actual name of the DLL prototype record itself. The documentation recommends that you give it a name of

   "DLL_" : <dllname>

e.g. If you want to use a function from User32.DLL you'd prototype those functions in the DLL_USER32 record in the SYSPROCS table.

This is all well and good, and Revelation supply prototype records for several of the core Windows DLLs because many internal OI components use functions exported from them... and herein lies the problem:

If you make changes to the Revelation-supplied prototype records there is a good chance that they will be overwritten on a subsequent OpenInsight upgrade if Revelation decide to release an updated version.

To avoid this you should create a unique name for your prototype record - for example here at Sprezz HQ we tend to use "ZZ" or "ZZX" a lot, so if we're prototyping functions from User32.DLL we'd be updating a record called "DLL_ZZX_USER32".

The actual name of the prototype record has no bearing in the name of the DLL loaded at runtime - it's only used when you run Declare_Fcns() to create the stub programs (the actual runtime DLL name is contained on line 1 of the prototype record). You could have called your prototype record DLL_BOZOSLIVEHERE and you'd still be able to call the functions from User32.DLL


Naming the DLL functions

The second issue is the name of the actual prototyped functions themselves. Depending on the results you wish to achieve it is possible that a DLL function may be able to be prototyped in more than one way.

e.g. If you have a function that expects a pointer to a string you could prototype it as:

   INT STDCALL MyFunc( LPSTR )

or

   INT STDCALL MyFunc( LPVOID )

The first version expects OpenEngine to get the pointer to a Basic+ string variable and pass it to the function for you, while the second version expects you to provide your own pointer to a string variable via the GetPointer() function (There are valid reasons for being able have more than one way of defining the function argument types, but that's a story for another post...). Both definitions would create a DLL stub program in SYSOBJ called $MYFUNC so you could use MyFunc() in a Basic+ program.

You can probably see what's coming here. If MyFunc is defined in more than one prototype record and the definitions within are different then you have the potential for another naming collision. A case in point is the FindWindow() API function exported from User32.DLL - Many years ago I created my own prototype record to hold my own versions of some User32 functions. My definition of FindWindow was different from the one Revelation supplied. When I created my FindWindow the entire OI system stopped working as some internal OI functions were relying on the Revelation version!

The solution here is to alias the DLL function using the "as" keyword in your prototype so that your stub program has a unique name too.

e.g.

   INT STDCALL MyFunc( LPSTR ) as zzx_MyFunc

This creates a stub program in SYSOBJ as $ZZX_MYFUNC - You'd use zzx_MyFunc() in your Basic+ programs but it would still use the real MyFunc() function in the DLL at runtime.

(Revelation documentation on using the AS keyword can be found on their website here

Labels: , , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]



<< Home

Pixel
Pixel Footer R1 C1 Pixel
Pixel
Pixel
Pixel