Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.server -> Re: ORA-06522: undefined symbols error
On Fri, 29 Oct 2004 16:27:03 -0700, belanna wrote:
> I have a c++ program that is called from a c program. There is an
> oracle library calling the c program. The c++ library uses extern "C"
> so it can be called from the c program. It runs fine from an
> executable on the command line, but oracle cannot resolve t he c++
> symbols. I know this is a problem with making the c++ library, but
> don't know what it is.
The problem is that you have badly mixed up concepts. C++ allows nasty practices called "method overloading" and "polymorphism". Method overloading allows you to have several different functions with the same name, as long as they have different signatures (see the Gospel of Stroustrup). Polymorphisms makes it possible to invoke the right function when somebody uses something like this: (myobj *)p->my_method(); Again, see the Gospel of Stroustrup. To be able to that, C++ compilers do something called "name mangling". The "extern C" declaration doesn't make C++ callable from outside, it tells the compiler that "signature" will not be included in the symbol name for that routine. Here is part of the "nm" listing from a library that used in a C++ program which works with oracle:
U __cxa_allocate_exception U __cxa_throw U __gxx_personality_v0 U _IO_putc U OCIAttrGet U OCIBindByName U OCIBindByPos U OCIDefineByPos U OCIHandleAlloc U OCIHandleFree U OCIParamGet U OCIStmtExecute U OCIStmtFetch U OCIStmtPrepare U printf U stdout U strncpy U _Z12createColumnP16ColumnDescriptori 00000be0 T _Z12DisplayTitleP9OciCursor U _ZdlPv U _ZN10OciContext10CheckErrorEi U _ZN10OciContext8GetErrorEv 00000000 W _ZN13lib_exceptionC1Ei U _ZN8OciErrorC1EP10OciContext 00000b70 T _ZN9OciCursor10DisplayRowEic 000009e4 T _ZN9OciCursor12FunctionTypeEv 00000a28 T _ZN9OciCursor13MakeResultSetEi 0000098c T _ZN9OciCursor14GetColumnCountEv 0000078c T _ZN9OciCursor14OciDescribePosEi 0000047c T _ZN9OciCursor4BindEP6columni 0000058c T _ZN9OciCursor4BindEP6columnPc 000004d4 T _ZN9OciCursor4BindEPS_i 000005fc T _ZN9OciCursor4BindEPS_Pc 00000354 T _ZN9OciCursor4ExecEi 00000424 T _ZN9OciCursor5BindnEP6columniPi 0000051c T _ZN9OciCursor5BindnEP6columnPcPi 000006b0 T _ZN9OciCursor5FetchEi 000001c0 T _ZN9OciCursor5ParseEPKc 0000065c T _ZN9OciCursor6DefineEP6columni000003e0 T _ZN9OciCursor8RowCountEv
If you take a look at the following part
U OCIStmtExecute U OCIStmtFetch U OCIStmtPrepare U printf
You will notice that the "extern C" symbols like "printf" have easily recognizable names, without any funny characters, while symbols defined in the library have names like:
000001c0 T _ZN9OciCursor5ParseEPKc 0000065c T _ZN9OciCursor6DefineEP6columni 000003e0 T _ZN9OciCursor8RowCountEv 000000e0 T _ZN9OciCursorC1EPKcP10OciContextP6OciEnv
where the name includes the class name, the function name and signature.
Now, when you decide to map a C routine to a PL/SQL procedure, oracle will load the specified library into the listener process using "dlopen" library function and will map your function using a call to "dlsym" (if I am not mistaken, google or man pages should be able to help you with those). To be able to do that, you have to describe the exact location and the name of the library (aka "CREATE LIBRARY") and give it the EXACT NAME of the linker symbol that you want to use from that library. C++ compiler produces horribly mutilated names, not the exact ones. Even worse, each C++ compiler has its own Torquemada-inspired method of mangling names, which means that Oracle cannot possibly know which routine you would like to use. I believe that in Oracle v18, they'll come up with the RPM (Read Programmers Mind) feature, so that oracle will be able to use even badly written C++ routines as external procedures. I'm sure that this will be incorporated in the Omlet software much before that. May the farce be with you.
-- Artificial Intelligence is no match for natural stupidity.Received on Sun Oct 31 2004 - 16:56:11 CST