I craeted a function called Connect2DB()
its prototype is: extern int Connect2DB(OCI_Connection cn, OCI_Statement st, OCI_Error *err);
I call this function using Connect2DB(cn,st,err)
Inside the function cn gets a value, but when returning to the caller program cn equals NULL.
cn = OCI_ConnectionCreate("XE","system","manager",OCI_SESSION_DEFAULT);
if (cn == NULL) printf("cn is NULL\n");
else puts("cn inside Connect2DB() is not NULL");
if (!cn) return(False);
st = OCI_StatementCreate(cn);
return(True);
}
I get
-
cn inside Connect2DB() is not NULL
Return Status is: 1
cn After returning from Connect2DB() is NULL
cn is a pointer, so it should hold the address to a OCI_Connection struct after returning from Connect2DB()
but is holds NULL instead.
Any idea why?
Thanks,
Gillian
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
extern int SelectFromTable(void st, void verr);
extern int InitConnection(void verr);
extern int Connect2DB(void cn, void st, void err);
extern void err_handler(void err, short ExitFlg);
extern void print_version(void vcn);
extern void DisconnectDB(void cn);
-
int mtmain()
{
void verr, vcn, *vst;
if (!InitConnection(&verr)) err_handler(verr,True);
if (!Connect2DB(&vcn,&vst,&verr)) err_handler(verr,True);
print_version(vcn);
if (!SelectFromTable(vst,&verr)) err_handler(verr,False);
DisconnectDB(vcn);
CleanAll();
return EXIT_SUCCESS;
}
InitConnection Dunction:
extern int InitConnection(void *verr)
{
OCI_Error err = NULL;
err = (OCI_Error ) verr;
if (!OCI_Initialize(NULL,NULL,OCI_ENV_DEFAULT)) return(False);
*verr = err;
return(True);
cn = OCI_ConnectionCreate("XE","system","manager",OCI_SESSION_DEFAULT);
if (cn == NULL) printf("cn is NULL\n");
if (!(cn)) return(False);
When I run the program from command line (cmd.exe) it works,
but when I run it from application console (Pelles C interface), it failes right on the first function - InitConnection()
Any ideas?
Gillian
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
/ ------------------------------------------------------------------------ *
* main
* ------------------------------------------------------------------------ /
int main()
{
void verr, vcn, *vst;
if (!InitConnection(&verr)) ErrorHandling(verr,True);
if (!Connect2DB(&vcn,&vst,&verr,DBName,UserName,Password)) ErrorHandling(verr,True);
print_version(vcn);
if (!SelectFromTable(vst,&verr,SQLCmd)) ErrorHandling(verr,False);
DisconnectDB(vcn);
CleanAll();
printf("\npress any key to exit...");
getchar();
return True;
Once again, you haven't supplied an error handler to OCI_Initiliaze(). If you do not, you'll never retreive an error handle !!!!
Take two minutes to look at your own code : in InitConnection(), you're calling ErrorHandling() with a NULL OCi_Error handle...
What you should do :
1 - Supply to OCI_Initialize() an error handle (the prototype is in the documentation)
2 - When an error occurs, you can retreive the error attributes, locally in the handler
3 - Ouput the error attributes from inside the handler
4 - if you really want to raise those attributes outside the handler, wnat you can do is
A - create your own error structure
B - declare a static error structure variable
C - copy the OCI_Error handle attributes to your own structure
D - is a OCILIB function returns FALSE, you can use your static variable to access the error attributes
Vincent.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Vincent.
I craeted a function called Connect2DB()
its prototype is: extern int Connect2DB(OCI_Connection cn, OCI_Statement st, OCI_Error *err);
I call this function using Connect2DB(cn,st,err)
Inside the function cn gets a value, but when returning to the caller program cn equals NULL.
when I Run the program
-
OCI_Error err = NULL;
OCI_Connection cn = NULL;
OCI_Statement *st = NULL;
This is the function:
extern int Connect2DB(OCI_Connection cn, OCI_Statement st, OCI_Error err)
{
OCI_Connection cn1;
}
I get
-
cn inside Connect2DB() is not NULL
Return Status is: 1
cn After returning from Connect2DB() is NULL
cn is a pointer, so it should hold the address to a OCI_Connection struct after returning from Connect2DB()
but is holds NULL instead.
Any idea why?
Thanks,
Gillian
Hi,
Sorry for misunderstanding,
Now it looks like this.
if (!OCI_Initialize(ErrorHandling,NULL,OCI_ENV_DEFAULT)) return(False);
Hi,
In fact, it's normal that when your function returns, the value of cn is NULL.
Because the C language only knows one way to pass parameters : by value.
It means that it's a copy of the pointer 'cn' that is used inside the your function...
Your orignal pointer is not modified !! Same for 'st' !
What you should do is to pass the address of your pointers 'cn' and 'st'.
Like :
extern int Connect2DB(OCI_Connection cn, OCI_Statement st, OCI_Error *err);
And call it as :
Connect2DB(&cn,&st,&err);
Why do you pass an OCI_Error pointer ?
Vincent
Hi,
Thanks it works.
The reason I do that is because I want OCILIB to be transparent to the top level program/programers
Take a look at this code, it works.
Top level Program:
/ ------------------------------------------------------------------------ *
* prototypes
* ------------------------------------------------------------------------ /
extern int SelectFromTable(void st, void verr);
extern int InitConnection(void verr);
extern int Connect2DB(void cn, void st, void err);
extern void err_handler(void err, short ExitFlg);
extern void print_version(void vcn);
extern void DisconnectDB(void cn);
-
int mtmain()
{
void verr, vcn, *vst;
}
InitConnection Dunction:
extern int InitConnection(void *verr)
{
OCI_Error err = NULL;
err = (OCI_Error ) verr;
}
Connect2DB function:
extern int Connect2DB(void vcn, void vst, OCI_Error err)
{
OCI_Connection cn;
OCI_Statement *st = NULL;
st = OCI_StatementCreate(cn);
vcn = (OCI_Connection ) cn;
vst = (OCI_Statement ) st;
return(True);
}
SelectFromTable Function:
extern int SelectFromTable(OCI_Statement st, OCI_Error err)
{
OCI_Resultset *rs = NULL;
}
print_frmt("count : %i\n", OCI_GetRowCount(rs));
return(True);
}
err_handler Function:
extern void err_handler(OCI_Error *err, short ExitFlg)
{
print_text("\n");
}
DisconnectDB Function:
extern void DisconnectDB(void vcn)
{
OCI_Connection cn = NULL;
cn = (OCI_Connection *) vcn;
printf("Disconnecting ...\n");
OCI_ConnectionFree(cn);
}
As you can see, in the top level program, OCILIB is not declared, and the program is indifferent to OCI.
Gillian
Hi Gillian,
You're not using the void *err parameter in your functions..
Anyway ,the only way to get an OCI_Error handle is inside the error handler callback that you cna supply to OCI_Initialize().
And the OCI_Error handle passed to the callback is avaible only inside the callback. When the callback returns, the error handler is destroyed !
The mechanisms you're using for error handling cannot work...
Hi
Have another question,
When I run the program from command line (cmd.exe) it works,
but when I run it from application console (Pelles C interface), it failes right on the first function - InitConnection()
Any ideas?
Gillian
See my previous answer...
Sorry I copied the old version of err_handler()
Now It looks like this:
include <stdio.h>
include <stdlib.h>
include "DBHandle_literals.h"
include "GlobalDef.h"
/ ------------------------------------------------------------------------ *
* prototypes
* ------------------------------------------------------------------------ /
extern int SelectFromTable(void st, void verr, char SQLCmd);
extern int InitConnection(void verr);
extern int Connect2DB(void vcn, void vst, void verr,char DBName, char UserName, char Password);
extern void ErrorHandling(void verr, short ExitFlg);
extern void print_version(void vcn);
extern void DisconnectDB(void vcn);
extern void CleanAll(void);
static char DBName = "XE", UserName = "system", Password = "manager";
static char SQLCmd = "SELECT name,age FROM persons";
/ ------------------------------------------------------------------------ *
* main
* ------------------------------------------------------------------------ /
int main()
{
void verr, vcn, *vst;
}
extern void ErrorHandling(void verr, short ExitFlg)
{
OCI_Error err = NULL;
}
What about the last question I asked?
As i said, an OCI_Error handle "lives" the time of the callback.
If you get back the handle ouside the callback, it will point to already freed memory and leads to a segfault.
For your last question, is the ocilib dll accessible to your program ? Check the path, the location where you put the dll, ...
Your actual error handing will fail at the first error raised by ocilib.
Start by change it first...
Hi Vincent, Is this a better error handling?
The error handling is within the function.
-
Call to InitConnection()
-
InitConnection Function:
extern void ErrorHandling(OCI_Error *err, short ExitFlg);
extern int InitConnection()
{
OCI_Error *err = NULL;
}
ErrorHandling Function:
extern void ErrorHandling(OCI_Error err, short ExitFlg)
{
if (OCI_ErrorGetType(err) == OCI_ERR_API)
{
const mtext sql = OCI_GetSql(OCI_ErrorGetStatement(err));
}
Once again, you haven't supplied an error handler to OCI_Initiliaze(). If you do not, you'll never retreive an error handle !!!!
Take two minutes to look at your own code : in InitConnection(), you're calling ErrorHandling() with a NULL OCi_Error handle...
What you should do :
1 - Supply to OCI_Initialize() an error handle (the prototype is in the documentation)
2 - When an error occurs, you can retreive the error attributes, locally in the handler
3 - Ouput the error attributes from inside the handler
4 - if you really want to raise those attributes outside the handler, wnat you can do is
A - create your own error structure
B - declare a static error structure variable
C - copy the OCI_Error handle attributes to your own structure
D - is a OCILIB function returns FALSE, you can use your static variable to access the error attributes
Vincent.