Using EXPORT in classes

I have a few classes with complex business rules and processes, but I’ve just been INCLUDEing them wherever I needed, resulting in their code being compiled in all the dlls.

After some unexpected behavior caused by this, I decided to create a new dll with all the classes and properly export them.

I found a post by also where he explains the EXPORT attribute, and it works great for classes.

One limitation of EXPORT is that it doesn’t have a conditional parameter (like DLL or LINK) so the class must have its first line declared twice with conditional compilation. After a few iterations, I’ve arrived at a source code format that I think is simple to implement and readable.

This is how the inc file looks like:

  COMPILE('|',ExportClasses=1)
ExampleClassType      CLASS,MODULE('ExampleClassType'),LINK('ExampleClassType',1),EXPORT,TYPE |
  COMPILE('|',ExportClasses=0)
ExampleClassType      CLASS,MODULE(''),DLL(1),TYPE |
ExampleMethod           PROCEDURE(STRING pText,BOOL pUpper = FALSE),STRING
                      END

In the dll where the classes are exported, you only need two lines:

ExportClasses       EQUATE(1) 
  INCLUDE('ExampleClassType.inc'),ONCE

And in all the other dlls and exes, the normal line:

  INCLUDE('ExampleClassType.inc'),ONCE

There is no need to add flags to the project, as the EQUATE handles the conditional compile. And, of course, there is no need to add anything to the .exp file, because the EXPORT attribute takes care of that.

I decided to use COMPILE('|'...) and a superfluos line continuation symbol | to save two lines in the class declaration, and COMPILE(...,flag=0) instead of OMIT for better readability.

Since the conditional compilation is handling which line to use, there is no need to use flags in the class declarations, so I used 1 and '' as parameters for LINK, DLL and MODULE, and omitted them where appropriate.

Here is a simple test project in github.

Carlos

2 Likes

You mention External several times, yet I don’t see any use of EXTERNAL. Did you mean to say EXPORT instead?

Yes, fixed, thank you.

EXPORT is the typical attribute of boolean type: it’s TRUE if present and FALSE if missing. There are quite many such attributes, for example CREATE on FILEs. DLL and LINK attributes are not boolean.

There is another way - to use the EQUATE to define the synonym for a keyword. For example,

  COMPILE('===', _EXPORT_)
_EXPORT    EQUATE(EXPORT)
! ===

  OMIT('===', _EXPORT_)
_EXPORT    EQUATE(BINDABLE)
! ===


TestClass  CLASS,TYPE,_EXPORT,BINDABLE
V1           LONG
V2           STRING(32)

M1           PROCEDURE()
M2           PROCEDURE()
           END

The BINDABLE attribute is useful here because it does nothing but can be used multiple times in one declaration.

I used the conditional compilation here for clarity. Synonyms for identifiers (including keywords) can be defined in the project directly using the define pragma.

5 Likes