Writing a Win32 DLL in C++ for Oracle extproc

I was recently tasked with writing a Win32 DLL containing functionality to be used by Oracle procedures and functions via extproc. This post describes the steps required to achieve this using Microsoft Visual Studio 2005 and Oracle 10g.

Creating the DLL

I used Visual Studio 2005 for this but I’m sure 2003 or 2008 can be used in a similar way. The important step is to choose the appropriate project type. Do the following:

  • File > New > Project
  • Project type: Visual C++ > Win32
  • Template: Win32 Console Application
  • Give your project a name (I have used “rwnet64” in this example)

001-create-project

When you click OK you should see the Win32 Application Wizard:

002-create-project

Click Next to configure the application settings. As shown here, ensure that the DLL radio button is selected:

003-create-project

Click Finish to see the generated code:

004-configuration

The highlighted block shows a default entry point for the DLL. This can be safely deleted.

At this point the project should compile and we’re ready to add some code.

The following is an example of a simple function. The important thing to note is the compiler directive __declspec(dllexport) which is required for extproc to load the DLL successfully.

extern "C" __declspec(dllexport) int addTen (int val)
{
    return val + 10;
}

The project should compile. Build the DLL as a Release build (a Debug build won’t work with extproc), then copy it over to your Oracle server’s BIN or LIB folder.

Preparing Oracle

I’m going to assume that your instance of Oracle is already configured to use extproc, i.e. that listener.ora and tnsnames.ora have been set up correctly. I might come back and explain how to do this later, but in the meantime just Google for it.

To call our DLL from a PL/SQL routine via extproc, we need:

  1. an Oracle library
  2. a PL/SQL routine

The Oracle library can be created like this at a SQL*Plus prompt:

> create or replace library rwnet64
  as 'e:\oracle\product\10.2.0\db_2\lib\rwnet64.dll;
 
Library created.

Note: If this fails because your user doesn’t have the necessary privileges, run the following from a SQL*Plus prompt connected as the system user (where myuser is, er, your user):

> grant create library to myuser;

With the Oracle library created, we now need some code! Here’s an example package body:

CREATE OR REPLACE package body dlltest_pkg AS
 
    FUNCTION addTen(num IN pls_integer)
    RETURN pls_integer
    AS external
    LANGUAGE c
    library rwnet64
    name "addTen"
    parameters (num INT, RETURN INT);
 
END dlltest_pkg;
/

Once you’ve created the package (and you’ll need to write the accompanying package header script) the DLL can now be tested from a SQL*Plus prompt with the following:

> select dlltest_pkg.addTen(5) from dual;
 
DLLTEST_PKG.ADDTEN(5)
---------------------
 15

And that proves it: calling a function in a Win32 DLL written in C++ from a function in an Oracle package via extproc.

If you got this far you are now at liberty to create useful functionality in your DLL. One thing to watch out for is the choice of datatypes between the DLL and PL/SQL. This table is a useful starting point for ironing out any issues.

Good luck!

Leave a Reply