带有Delphi DLL的Oracle外部过程​​

时间:2019-05-10 07:33:01

标签: oracle delphi dll oracle-sqldeveloper

我一直在尝试为Windows 10上的Oracle Database 18c配置“外部过程”功能。

文档声称,要设置此功能,基本上只需要在extrproc.ora中设置环境值-就我而言,它只是以下一行的内容:SET EXTPROC_DLLS=ANY(出于测试目的)

我已经创建了一个DLL,以使用带有以下代码的Delphi来测试我的配置:

library testdll;

function Sum(x, y: Integer): Integer; stdcall;
begin
  Result := x + y;
end;

function Subtract(x, y: Integer): Integer; stdcall;
begin
  Result := x - y;
end;

procedure TEST; stdcall;
begin

end;

exports
  TEST,
  Sum,
  Subtract;

begin

end.

所以我的第一个问题是:是否需要将DLL编译为x64或x86?另外,调用约定stdcall是否与Oracle 18c兼容?

此外,我还使用以下方法在数据库中创建了“图书馆别名”:

CREATE OR REPLACE LIBRARY MySchema.TESTDLL AS 'C:\testdll.dll'

外部程序已由

发布
create or replace PROCEDURE TESTPROCEDURE
AS LANGUAGE C 
NAME "TEST"
LIBRARY TESTDLL;

现在我已经在数据库上进行了所有设置,我尝试调用该过程:

begin
TESTPROCEDURE();
end;

但是当我尝试调用它时,出现以下错误:

ORA-06520: PL/SQL: Fehler beim Laden der externen Library
ORA-06522: Unable to load DLL
ORA-06512: in "MySchema.TESTPROCEDURE", Zeile 1
ORA-06512: in Zeile 2
06520. 00000 -  "PL/SQL: Error loading external library"
*Cause:    An error was detected by PL/SQL trying to load the external
           library dynamically.
*Action:   Check the stacked error (if any) for more details.

信息:

  • 在我调用过程之后,数据库会正确地生成extproc.exe

我如何才能正常工作并且Delphi DLL是否兼容?

这是我的listener.ora文件:

# listener.ora Network Configuration File: C:\app\oracle\product\18.0.0\dbhomeXE\NETWORK\ADMIN\listener.ora
# Generated by Oracle configuration tools.

DEFAULT_SERVICE_LISTENER = XE

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = CLRExtProc)
      (ORACLE_HOME = C:\app\oracle\product\18.0.0\dbhomeXE)
      (PROGRAM = extproc)
      (ENVS = "EXTPROC_DLLS=ONLY:C:\app\oracle\product\18.0.0\dbhomeXE\bin\oraclr18.dll")
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )

这是我的tnsnames.ora文件:

# tnsnames.ora Network Configuration File: C:\app\oracle\product\18.0.0\dbhomeXE\NETWORK\ADMIN\tnsnames.ora
# Generated by Oracle configuration tools.

XE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XE)
    )
  )

LISTENER_XE =
  (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))


ORACLR_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
    (CONNECT_DATA =
      (SID = CLRExtProc)
      (PRESENTATION = RO)
    )
  )

任何想法我的配置有什么问题吗?

编辑: 这是来自数据库的.c dll示例代码:

/*
** Copyright (c) 1997 by Oracle Corporation
**
** NAME
**   EXTERN.C 
**
** DESCRIPTION
**   Sample Windows NT External Procedure: find_max 
**
*/

#include <windows.h>

#define NullValue -1

/*
  This function simply returns the returns the larger of x and y.
*/

long __declspec(dllexport) find_max(long    x, 
                    short   x_indicator, 
                                    long    y, 
                        short       y_indicator, 
                    short       *ret_indicator)
{
   /* It can be tricky to debug DLL's that are being called by a process
      that is spawned only when needed, as in this case.  
      Therefore try using the DebugBreak(); command.  
      This will start your debugger.  Uncomment the following line and
      you can step right into your code.
   */
   /* DebugBreak();  */

   /* first check to see if you have any nulls */
   /* Just return a null if either x or y is null */

   if ( x_indicator==NullValue || y_indicator==NullValue) {
      *ret_indicator = NullValue;   
      return(0);
   } else { 
      *ret_indicator = 0;        /* Signify that return value is not null */
      if (x >= y) return x;
      else return y;
   }
}

这是make.bat文件:

REM USAGE: just type MAKE
if (%PROCESSOR_ARCHITECTURE%)==(IA64) goto win64_ia64
if (%PROCESSOR_ARCHITECTURE%)==(AMD64) goto win64_amd64
 cl -I. /LD -Zi extern.c /link msvcrt.lib /nod:libcmt /DLL
 goto fi
:win64_ia64
 cl /DWIN64 /D_WIN64 /DSS_64BIT_SERVER /D_IA64_=1 -I. /LD -Zi extern.c /link msvcrt.lib /nod:libcmt /DLL
 goto fi
:win64_amd64
 cl /GS- /DWIN64 /D_WIN64 /DSS_64BIT_SERVER /D_AMD64_=1 -I. /LD -Zi extern.c /link msvcrt.lib /MACHINE:AMD64 /nod:libcmt /DLL
 goto fi
:fi

1 个答案:

答案 0 :(得分:1)

根据提供的信息,我可以看到以下内容:

  • C示例被编译为64位DLL。
  • C示例未指定调用约定,因此使用默认值cdecl
  • 示例C函数接受5个参数,但您的函数仅接受2个。