linkend="ecpg-lo-example"/> shows an example program that
illustrates how to create, write, and read a large object in an
ECPG application.
</para>
<example id="ecpg-lo-example">
<title>ECPG Program Accessing Large Objects</title>
<programlisting><![CDATA[
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
#include <libpq/libpq-fs.h>
EXEC SQL WHENEVER SQLERROR STOP;
int
main(void)
{
PGconn *conn;
Oid loid;
int fd;
char buf[256];
int buflen = 256;
char buf2[256];
int rc;
memset(buf, 1, buflen);
EXEC SQL CONNECT TO testdb AS con1;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;
conn = ECPGget_PGconn("con1");
printf("conn = %p\n", conn);
/* create */
loid = lo_create(conn, 0);
if (loid < 0)
printf("lo_create() failed: %s", PQerrorMessage(conn));
printf("loid = %d\n", loid);
/* write test */
fd = lo_open(conn, loid, INV_READ|INV_WRITE);
if (fd < 0)
printf("lo_open() failed: %s", PQerrorMessage(conn));
printf("fd = %d\n", fd);
rc = lo_write(conn, fd, buf, buflen);
if (rc < 0)
printf("lo_write() failed\n");
rc = lo_close(conn, fd);
if (rc < 0)
printf("lo_close() failed: %s", PQerrorMessage(conn));
/* read test */
fd = lo_open(conn, loid, INV_READ);
if (fd < 0)
printf("lo_open() failed: %s", PQerrorMessage(conn));
printf("fd = %d\n", fd);
rc = lo_read(conn, fd, buf2, buflen);
if (rc < 0)
printf("lo_read() failed\n");
rc = lo_close(conn, fd);
if (rc < 0)
printf("lo_close() failed: %s", PQerrorMessage(conn));
/* check */
rc = memcmp(buf, buf2, buflen);
printf("memcmp() = %d\n", rc);
/* cleanup */
rc = lo_unlink(conn, loid);
if (rc < 0)
printf("lo_unlink() failed: %s", PQerrorMessage(conn));
EXEC SQL COMMIT;
EXEC SQL DISCONNECT ALL;
return 0;
}
]]></programlisting>
</example>
</sect1>
<sect1 id="ecpg-cpp">
<title><acronym>C++</acronym> Applications</title>
<para>
ECPG has some limited support for C++ applications. This section
describes some caveats.
</para>
<para>
The <command>ecpg</command> preprocessor takes an input file
written in C (or something like C) and embedded SQL commands,
converts the embedded SQL commands into C language chunks, and
finally generates a <filename>.c</filename> file. The header file
declarations of the library functions used by the C language chunks
that <command>ecpg</command> generates are wrapped
in <literal>extern "C" { ... }</literal> blocks when used under
C++, so they should work seamlessly in C++.
</para>
<para>
In general, however, the <command>ecpg</command> preprocessor only
understands C; it does not handle the special syntax and reserved
words of the C++ language. So, some embedded SQL 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.