PL/SQLからDLLを呼び出す

珍しく仕事関連な話題。PL/SQLからDLLを呼び出すにはどうすれば良いか質問されたので、ちょっと調べてみました。
listener.oraに以下の記述を追加。

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
    )
    ...
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = C:\Oracle\Ora92)
      (PROGRAM = extproc)
    )
    ...
  )

ORACLE_HOMEは環境に合わせる。

tnsnames.oraに以下の記述を追加。

EXTPROC_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
      (PRESENTATION = RO)
    )
  )

ここでリスナーを再起動。

PL/SQLから呼び出すサンプルDLLを作ってみる。
hello.c

#include <stdio.h>

__declspec(dllexport) void hello(char* key, char* msg) 
{
    sprintf (msg, "Hello, %s", key);
}

コンパイルしてhello.dllを作成する。

$ cl /MD /LD hello.c

PL/SQLから呼び出すDLLは%ORACLE_HOME%\binに置く(windows版の制限?)

$ copy hello.dll %ORACLE_HOME%\bin

DLLを呼び出すプロシージャを用意する。

CREATE OR REPLACE LIBRARY hellolib AS '$ORACLE\bin\hello.dll';

CREATE OR REPLACE PROCEDURE Hello (key IN VARCHAR2, msg OUT VARCHAR2)
IS EXTERNAL
    NAME "hello"
    LIBRARY hellolib
    PARAMETERS (key STRING, msg STRING);

これをSQL*Plusで流す。

SQL*Plusから呼び出してみる。

> var msg VARCHAR2(255);
> call Hello ('World', :msg);
> print msg;
Hello, World

メモを会社に置いてきてしまい、思い出しながらなので間違っているかも。(^^;

(追記) 案の定間違えていた・・・