code written in
C++ application code that uses complicated features specific to C++
might fail to be preprocessed correctly or might not work as
expected.
</para>
<para>
A safe way to use the embedded SQL code in a C++ application is
hiding the ECPG calls in a C module, which the C++ application code
calls into to access the database, and linking that together with
the rest of the C++ code. See <xref linkend="ecpg-cpp-and-c"/>
about that.
</para>
<sect2 id="ecpg-cpp-scope">
<title>Scope for Host Variables</title>
<para>
The <command>ecpg</command> preprocessor understands the scope of
variables in C. In the C language, this is rather simple because
the scopes of variables is based on their code blocks. In C++,
however, the class member variables are referenced in a different
code block from the declared position, so
the <command>ecpg</command> preprocessor will not understand the
scope of the class member variables.
</para>
<para>
For example, in the following case, the <command>ecpg</command>
preprocessor cannot find any declaration for the
variable <literal>dbname</literal> in the <literal>test</literal>
method, so an error will occur.
<programlisting>
class TestCpp
{
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
EXEC SQL END DECLARE SECTION;
public:
TestCpp();
void test();
~TestCpp();
};
TestCpp::TestCpp()
{
EXEC SQL CONNECT TO testdb1;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
}
void Test::test()
{
EXEC SQL SELECT current_database() INTO :dbname;
printf("current_database = %s\n", dbname);
}
TestCpp::~TestCpp()
{
EXEC SQL DISCONNECT ALL;
}
</programlisting>
This code will result in an error like this:
<screen>
<userinput>ecpg test_cpp.pgc</userinput>
test_cpp.pgc:28: ERROR: variable "dbname" is not declared
</screen>
</para>
<para>
To avoid this scope issue, the <literal>test</literal> method
could be modified to use a local variable as intermediate storage.
But this approach is only a poor workaround, because it uglifies
the code and reduces performance.
<programlisting>
void TestCpp::test()
{
EXEC SQL BEGIN DECLARE SECTION;
char tmp[1024];
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT current_database() INTO :tmp;
strlcpy(dbname, tmp, sizeof(tmp));
printf("current_database = %s\n", dbname);
}
</programlisting>
</para>
</sect2>
<sect2 id="ecpg-cpp-and-c">
<title>C++ Application Development with External C Module</title>
<para>
If you understand these technical limitations of
the <command>ecpg</command> preprocessor in C++, you might come to
the conclusion that linking C objects and C++ objects at the link
stage to enable C++ applications to use ECPG features could be
better than writing some embedded SQL commands in C++ code
directly. This section describes a way to separate some embedded
SQL commands from C++ application code with a simple example. In
this example, the application is implemented in C++, while C and
ECPG is used to connect to the PostgreSQL server.
</para>
<para>
Three kinds of files have to be created: a C file
(<filename>*.pgc</filename>), a header file, and a C++ file:
<variablelist>
<varlistentry id="ecpg-cpp-and-c-test-mod-pgc">
<term><filename>test_mod.pgc</filename></term>
<listitem>
<para>
A sub-routine module to execute SQL commands embedded in C.
It is going to be converted
into <filename>test_mod.c</filename> by the preprocessor.
<programlisting>
#include "test_mod.h"
#include <stdio.h>
void
db_connect()
{
EXEC SQL CONNECT TO testdb1;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
}
void
db_test()
{
EXEC SQL BEGIN DECLARE SECTION;
char dbname[1024];
EXEC SQL END DECLARE SECTION;