Ask the C++ Pro 10-Minute Solutions

Create a "Universal" DLL
By Jonathan Wood

I've been getting a lot of questions lately about how to export functions from a DLL so that they can be called from any language that supports calling DLLs. Writing a DLL is pretty straightforward and there are many ways to expose DLL functionality. However, most of them involve mangling the names somewhat. I'm going to describe the process of exporting functions with their original names.

First, unless you must absolutely have C++ code, I recommend writing your DLL in C. Most of you are familiar with C++ name mangling. In addition, calls to C++ class members require a "this" pointer be passed as a hidden argument. Probably the only time this is worthwhile is when the routines will be called from C++. What I want to discuss here is making DLL functions available to languages such as Visual Basic.

You may need to implement your own DLL entry point function and you need to make sure your code uses the stdcall calling convention, but these steps depend on the compiler you are using. For example, with Visual C++, you can create your own entry point with something like /entry:"DLLEntry" on the command line. DLLEntry must refer to a routine in the form of the following.

/////////////////////////////////////////////////////////////////////
// DLL initialization and clean-up.
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
   switch(fdwReason) {

      case DLL_PROCESS_ATTACH:

         // Perform any DLL initialization here
         break;

      case DLL_PROCESS_DETACH:

         // Perform any DLL cleanup here
         break;

   }
   return TRUE;
}

To make sure you use the correct calling convention, tell your compiler to use the stdcall calling convention and/or use one of the constants defined in windows.h (and related files) such as WINAPI. A DLL routine might then look like this.

/////////////////////////////////////////////////////////////////////
// Shifts bits right for integers.
WORD WINAPI vbShiftRight(WORD nValue, WORD nBits)
{
   return (nValue >> nBits);
}

The next step is contrary to what you'll read in the Microsoft documentation. You need to create a .DEF file. This is the only way you'll prevent the above function from being exported as something along the lines of _vbShiftRight@1. That .DEF file can be as simple as the following.


EXPORTS
        vbShiftRight
	

Next, we need to call the function. In Visual Basic, you can use a declare statement.

Declare Function vbShiftRight Lib "MYDLL.DLL" (ByVal nValue As Integer, 
  ByVal nBits As Integer)

As Integer

Sub Test()
   Dim i As Integer
   i = vbShiftRight(4, 2)
   Debug.Assert i = 1
End Sub

If you want to make it really easy to call from VB, you can create a type library. This requires that you create and compile an ODL (object description language) file. This file should include the following lines:

module MyModule {
   [
      helpstring("Shifts the bits of an integer to the right."),
      entry("vbShiftRight")
   ]
   short _stdcall vbShiftRight([in] short nValue, [in] short nBits);
};

When VB loads a DLL's type library, function names and arguments will appear in VB's object browser. In addition, the argument types and names appears as the user types the statement and VB will produce an error if the user does not enter the correct type of arguments.

 
Other 10-Minute Solutions
 How to Change the Mouse Pointer without Flicker
 Setting Full Row Selection in ListView Control
 Automating Type Conversions with stringstream Objects
 Improving Memory Reallocation with Vectors
 How to Use <fstream> Classes for File I/O
 Casting About for Safe Typecasting
 Overloading Operator + the Right Way
 How to Create Persistent Objects
 Making Linked Lists More User-Friendly
 Preventing Glitches in Signal Processing
 Forcing Object Allocation on the Free-store
 Using String-Based Data Validation
 Implementing the 'Resource Acquisition Is Initialization' Idiom
 Simple Locks for Data Files
 Template Specializations
 Exception Handling
 Using Bit Fields in Data Optimization
 Using the Transform() Algorithm to Change a String's Case
 Use RTTI for Dynamic Type Identification
 Choosing the Right swap () Implementation
 Take Charge and Initialize Your Own Data
 Share Data Among Objects Using the Monostate Design Pattern
 String Manipulation Made Easy with std::string Algorithms
 Using typedef to Curb Miscreant Code
 Managing Objects' Construction Order
 Bitwise Operators: Combining Efficiency and Ease of Use
 Use Function Adapters to Extend Generic Algorithms' Usage
 Simplify Callback Dispatching with Enumerated Indexes
 Streamline Your Bulk I/O Operations with Stream Iterators
 Optimize Your Member Layout
 Preserve Code Safety with Conversion Operators
 Modify Your Base Class Interface in Derived Classes
 Tackle Common Programming Tasks Using the New <tuple> Library
 Use Local Classes for Proper Cleanup in Exception-enabled Apps
 Use multimap to Create Associative Containers with Duplicate Keys
 Enforcing Compile-time Constraints
 Facilitate Directory Operations with the <dirent.h> and <dir.h> Libraries
 Spruce Up Your Built-in Arrays
 Target 32- and 64-bit Platforms Together with a Few Simple Datatype Changes
 Restrict Object Allocation to Specific Memory Types
 Use the Pimpl Idiom to Reduce Compilation Time and Enhance Encapsulation
 Automate Resource Management with shared_ptr
 The Quick and Dirty Way to Add
 Pointing to Class Members
 Detecting Keystrokes While Your Application is Busy
 Linked Lists
 Programming the System Tray
 Create a "Universal" DLL
 Convert Path to Long Path Name
 Constructing an Object at a Pre-Determined Memory Position
 Declaring Classes and Member Functions in a Namespace
 Using the auto_ptr Class Template to Facilitate Dynamic Memory Management
 Using the random_shuffle() Algorithm to Randomize a Sequence of Elements
 Defining a Function Object
 Implementing the Singleton Design Pattern
 Declaring Function Pointers and Implementing Callbacks
 Overloading Operator << for a User-Defined Type
 Implementing a Stopwatch Class for Performance Measurements
 Creating and Accessing Environment Variables
 Executing an Object's Member Function in a Separate Thread
 Creating Heterogeneous Containers
 Overriding New and Delete
 Time and Date Manipulation
  Defining Functions with a Variable Argument List
 Optimize Abstract Operations with Function Templates




Sponsored Links


Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map
Jupiterweb networks

internet.comearthweb.comDevx.comClickZ

Search Jupiterweb:

Jupitermedia Corporation has four divisions:
JupiterWeb, JupiterResearch, JupiterEvents, and JupiterImages

Copyright 2004 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Jupitermedia Corporate Info | Newsletters | Tech Jobs | E-mail Offers