Я пытался настроить функцию «Внешние процедуры» для моей базы данных Oracle 18c в Windows 10.
В документации утверждается, что для настройки этой функции просто необходимо установить значения среды в 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)
)
)
Есть идеи, что может быть не так с моей конфигурацией?
Edit:
Это пример кода .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