Topic: exceptions and C/C++ mixing


Author: "Matt Seitz" <mseitz@meridian-data.com>
Date: 1999/07/01
Raw View
Yannick de Kercadio <kercadio@limsi.fr> wrote in message
news:3729DA30.41C6@limsi.fr...
>But there might be
> a way to tell the C++ compiler that some function should have a C name
> (without type information), while being written in C++.

There is.  Use "extern "C"" in the declaration.  For example:

extern "C" int foo();  //Declares function with C linkage, no name
decoration

See section 9.2.4 of THE C++ PROGRAMMING LANGUAGE, Third Edition.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Paul Grealish <paul.grealish@uk.geopak-tms.com>
Date: 1999/05/07
Raw View
Yannick de Kercadio wrote in message <3729DA30.41C6@limsi.fr>...
>Here is the problem. We want to design a C++ class to send SQL request
>to an Oracle Database.
>
>Oracle (in the old version we have) provides us only with an ESQL C
>pre-processor (Embedded SQL for C). This tool translates some SQL-like
>or SQL-linked lines into some valid C code. But not C++. Therefore, at
>least one compilation unit must be written in C.
>
>Right. Now, we want to transform any Oracle error into a C++ exception.
>ESQL C copes with errors using an exception-like interface :
>
>EXEC SQL WHENEVER SQLERROR DO my_C_function() ;


Stop right there!
That method of error handling is only for example purposes
only.  I realise it's what Oracle show in their
documentation but you shouldn't even consider it for
'proper' code.

(mod: I realise this completely off-topic but I've started now...)
What you should be doing is checking SQLCODE or
sqlca.sqlcode after each each 'executable' SQL statement.
SQLCODE (sqlca.sqlcode ) is effectively the return status
from each call to 'sqlcxt' which is the function
that executes each (executable) SQL statement.  You can see
where 'sqlcxt' is called by looking at the
post-processed code.  If you wish to raise an exception
then do so locally after examining the returned code.

I tend to reserve exceptions for truly exceptional
conditions.  When dealing with an external data source such
as a database I wouldn't treat any failure as an
'exceptional' condition - it's something that could be
reasonably expected.

+-------------------------------+
|         Paul Grealish         |
|    Bentley Transportation     |
|      Cambridge, England       |
|   paul.grealish@bentley.com   |
+-------------------------------+




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/05/06
Raw View
Yannick de Kercadio <kercadio@limsi.fr> writes:

>Here is the problem. We want to design a C++ class to send SQL request
>to an Oracle Database.

>Oracle (in the old version we have) provides us only with an ESQL C
>pre-processor (Embedded SQL for C). This tool translates some SQL-like
>or SQL-linked lines into some valid C code. But not C++. Therefore, at
>least one compilation unit must be written in C.

>Right. Now, we want to transform any Oracle error into a C++ exception.
>ESQL C copes with errors using an exception-like interface :

>EXEC SQL WHENEVER SQLERROR DO my_C_function() ;

>This line will be translated by the pre-processor into some C code.

>Well. Of course, C is not C++, and there is no way in my_C_function to
>know where we come from (i.e., from which C function the error comes).
>However, we would like to send an exception that a C++ catcher would
>receive somewhere...

>1st solution: use setjmp/longjmp in the C compilation unit, so that
>my_C_function() returns into the C code that raised the SQL error. From
>there, we can safely return to C++ with some error information.
>That's what we did, and it works. Or we wouldn't be posting on this
>group!

If the longjmp bypasses any C++ code with local objects that
need to be destroyed, the results of the program are undefined.
Use of setjmp/longjmp should be restricted to C code that
does not call any C++ functions. Better yet, don't use them
at all in a program which contains significant amounts of C++.

>2nd solution: call a C++ function from my_C_function().
>  Would it be possible at all? Is it possible to pass a C++ callback
>function to some C code?

Of course. Declare the C++ function to have C linkage.  The
linkage declaration does not imply what language the function
is written in. It specifies only the the calling conventions.

C code:
========
typedef int (*fp)(int);
void somefunc( fp callback )
{
    ...
    int i = callback(3);
    ...
}


C++ code:
=========
extern "C" {
    typedef int (*fp)(int);
    void somefunc(fp);
}
extern "C" int mycallback(int i)
{
    ...
}
int main()
{
    somefunc(mycallback);
}


--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James Kuyper <kuyper@wizard.net>
Date: 1999/05/06
Raw View
Yannick de Kercadio wrote:
....
> 1st solution: use setjmp/longjmp in the C compilation unit, so that
> my_C_function() returns into the C code that raised the SQL error. From
> there, we can safely return to C++ with some error information.
> That's what we did, and it works. Or we wouldn't be posting on this
> group!
>
> 2nd solution: call a C++ function from my_C_function().
>   Would it be possible at all? Is it possible to pass a C++ callback
> function to some C code? I guess the answer is 'no'. But there might be
> a way to tell the C++ compiler that some function should have a C name
> (without type information), while being written in C++.

Can language linkage help? In C++ code, you can call a function declared
as 'extern "C"' that's defined in a module written in C. You can also
define an 'extern "C"' function in C++ code, and that function will be
callable from C code:

module1.c:
 #include <stdio.h>
 extern void cpp_cfunc(void);
 void cfunc(void)
 {
  printf("In cfunc.\n");
  cppcfunc();
 }

module2.cpp:
 #include <stdio>
 extern "C" void cpp_cfunc()
 {
  std::printf("In cpp_cfunc.\n");
 }
 extern "C" void cfunc();
 void cppfunc()
 {
  std::printf("In cppfunc.\n");
  cfunc();
 }

Does this allow what you need?

>   If so, would it work? I mean, we are throwing from a C++ function
> called by a C function called by some *&^@ Oracle-specific C code called
> by a C function called by a C++ function (where we would like to come
> back, because the catcher is here!)
>
> 3rd solution: call setjmp in the C++ code, and pass the argument for
> longjmp to the C functions. Whenever an error occurs, call a longjmp
> with this argument.
>   Would it work? Is setjmp supported in C++.

Yes, setjmp/longjmp is supported in C++. However, there are some
complications with regard to undestroyed automatic objects when you call
longjmp(). Section 18.7 p4: "If any automatic objects would be destroyed
by a thrown exception transferring control to another (destination)
point in the program, then a call to longjmp(jbuf, val) at the throw
point that transfers control to the same (destination) point has
undefined behavior."
Because of this complication, I expect that it would be pretty rare for
a longjmp() call from within C++ code to be safe.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Dave Abrahams <abrahams@mediaone.net>
Date: 1999/05/06
Raw View
In article <3729DA30.41C6@limsi.fr> , Yannick de Kercadio
<kercadio@limsi.fr>  wrote:

> Here is the problem. We want to design a C++ class to send SQL request
> to an Oracle Database.
>
> Oracle (in the old version we have) provides us only with an ESQL C
> pre-processor (Embedded SQL for C). This tool translates some SQL-like
> or SQL-linked lines into some valid C code. But not C++. Therefore, at
> least one compilation unit must be written in C.

Of course, you can compile most C code with a C++ compiler. There are lots
of details missing in your post (at least for someone not familiar with
Oracle, like me), but: if the tool generates C code which is supposed to be
compiled and liked with something that they supply, then, yes, this code has
to be compiled as "C".

> Right. Now, we want to transform any Oracle error into a C++ exception.
> ESQL C copes with errors using an exception-like interface :
>
> EXEC SQL WHENEVER SQLERROR DO my_C_function() ;
>
> This line will be translated by the pre-processor into some C code.

I presume this means that my_C_function() will be called when an error
occurs. If so, that's very unlike exceptions, which don't generally trigger
callbacks.

> Well. Of course, C is not C++, and there is no way in my_C_function to
> know where we come from (i.e., from which C function the error comes).
> However, we would like to send an exception that a C++ catcher would
> receive somewhere...
>
> 1st solution: use setjmp/longjmp in the C compilation unit, so that
> my_C_function() returns into the C code that raised the SQL error. From
> there, we can safely return to C++ with some error information.
> That's what we did, and it works. Or we wouldn't be posting on this
> group!



Author: Yannick de Kercadio <kercadio@limsi.fr>
Date: 1999/05/04
Raw View
Here is the problem. We want to design a C++ class to send SQL request
to an Oracle Database.

Oracle (in the old version we have) provides us only with an ESQL C
pre-processor (Embedded SQL for C). This tool translates some SQL-like
or SQL-linked lines into some valid C code. But not C++. Therefore, at
least one compilation unit must be written in C.

Right. Now, we want to transform any Oracle error into a C++ exception.
ESQL C copes with errors using an exception-like interface :

EXEC SQL WHENEVER SQLERROR DO my_C_function() ;

This line will be translated by the pre-processor into some C code.

Well. Of course, C is not C++, and there is no way in my_C_function to
know where we come from (i.e., from which C function the error comes).
However, we would like to send an exception that a C++ catcher would
receive somewhere...

1st solution: use setjmp/longjmp in the C compilation unit, so that
my_C_function() returns into the C code that raised the SQL error. From
there, we can safely return to C++ with some error information.
That's what we did, and it works. Or we wouldn't be posting on this
group!

2nd solution: call a C++ function from my_C_function().
  Would it be possible at all? Is it possible to pass a C++ callback
function to some C code? I guess the answer is 'no'. But there might be
a way to tell the C++ compiler that some function should have a C name
(without type information), while being written in C++.

  If so, would it work? I mean, we are throwing from a C++ function
called by a C function called by some *&^@ Oracle-specific C code called
by a C function called by a C++ function (where we would like to come
back, because the catcher is here!)

3rd solution: call setjmp in the C++ code, and pass the argument for
longjmp to the C functions. Whenever an error occurs, call a longjmp
with this argument.
  Would it work? Is setjmp supported in C++.

When we write "would it work", it means "in compliance with the
standard". We can find some implementations on which it works, and some
others on which it does not work... It's just a matter of "how should we
be doing that?"

Thanks for having read this message so far!

--
Yannick de Kercadio
kercadio@limsi.fr
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]