OS/2 codes: compiler keywords exporting a symbol from a DLL without .def

The most basic way to export a symbol from a DLL is to list entries below EXPORTS keyword in .DEF file. However, this works for Visual Age C++(VAC) and gcc, but not for Open Watcom C/C++(OW). OW uses its own linker script, .lnk file, and EXPORT keyword not EXPORTS.

Because of this, if you want to write DLLs buildable by the above three compilers, you should maintain at least two files of .def for VAC and gcc, and .lnk for OW. This increases the complexity of maintence.

As well as, whenever symbols are exported newly, they should be added to .def and .lnk themselves. This is very annoying. Instead, it would be very convenient if exporting symbols in the source itself. All three compilers provide keywords for this.

1. Visual Age C++

VAC provides _Export keyword and #pragma export directive. Especially, _Export may be used in in-line style. For example,

void _Export dll_entry( void );

will export dll_entry() as a proper name according to its calling convention and linkage style.

2. Open Watcom C/C++

OW provides various ways. First is __export keyword and _export macro equivalent to __export. Second is __declspec( dllexport ) keyword. Third is #pragma aux sym export; directive. __export and __declspec( dllexport ) may be used in in-line style.

void __export dll_entry1( void );
void __declspec( dllexport ) dll_entry2( void );

3. gcc + kLIBC

gcc provides __declspec( dllexport ) to export a symbol from a DLL in the source.

void __declspec( dllexport ) dll_entry( void );

gcc does not provide #pragma directive for this.

4. macro for keywords

Keywords are different according to compilers. It's inefficiency to declare a symbol according to compilers whenever exporting a symbol. Instead, it would be a good way to define a macro for this.

#if defined(__IBMC__) || defined(__IBMCPP)
#define DLLENTRY _Export
#else
#define DLLENTRY __declspec( dllexport )
#endif

And it may be used like this:

void DLLENTRY dll_entry(void);

5. Calling convention

Now, we know that compilers provide keywords to export a symbol from a DLL. However, one problem still remains. It's a calling convention. Compiler's default calling convetion is different respectively.

Due to this, if you want to write DLLs compatible with all three compilers, you should specify a calling convention explicitly. Which calling convention should be used ?

OS/2 defines _System calling convention for this. This is best.

void _System DLLENTRY dll_entry(void);

Then dll_entry() will be exported as dll_entry without any decorations regardless of compilers.

6. Place to put keywords

The keywords may be placed in both a function declaration(prototype) and a function implementation. Regardless of the place, the keywords has the same effect. As a result, it would be better to place the keywords in a function implementation than in a function declaration. For example,

/** @file dll_entry.h */
void _System dll_entry(void);

/** @file dll_entry.c */
void DLLENTRY _System dll_entry(void)
{
...
}

Note that DLLENTRY is before _System. VAC and gcc do not care of this order. However, OW requires this.

7. Import library

To link against the DLL, you should generate an import library. At this time, an import library should be generated from a DLL directly. If you generate it from .DEF, some symbols which is exported by keywords but not listed in .DEF are not recorded to an import library. And it may leads to a linker failure due to an error such as 'undefined symbol'.

In case of gcc, you should build a DLL with -Zomf. ld linker does not support this feature.

8. Conclusion

Using keywords makes writing DLLs convenient very much. In addition, because all three compilers provide such keywords, it's possible to lower the complexicity with a macro of writing entires in .def or .lnk.

If you want to write DLLs for all compilers, consider to use the compiler keywords to export a symbol from a DLL instead of .def and .lnk.

댓글

이 블로그의 인기 게시물

토렌트: < 왕좌의 게임 > 시즌 1 ~ 시즌 8 완결편 마그넷

토렌트: NGC < 코스모스 > 우리말 더빙 전편(1편~13편) 마그넷

토렌트: < 스타워즈 > Ep.1 ~ Ep.6 마그넷