]> begriffs open source - ai-pg/blob - full-docs/txt/ecpg-cpp.txt
Convert HTML docs to more streamlined TXT
[ai-pg] / full-docs / txt / ecpg-cpp.txt
1
2 34.13. C++ Applications #
3
4    34.13.1. Scope for Host Variables
5    34.13.2. C++ Application Development with External C Module
6
7    ECPG has some limited support for C++ applications. This section
8    describes some caveats.
9
10    The ecpg preprocessor takes an input file written in C (or something
11    like C) and embedded SQL commands, converts the embedded SQL commands
12    into C language chunks, and finally generates a .c file. The header
13    file declarations of the library functions used by the C language
14    chunks that ecpg generates are wrapped in extern "C" { ... } blocks
15    when used under C++, so they should work seamlessly in C++.
16
17    In general, however, the ecpg preprocessor only understands C; it does
18    not handle the special syntax and reserved words of the C++ language.
19    So, some embedded SQL code written in C++ application code that uses
20    complicated features specific to C++ might fail to be preprocessed
21    correctly or might not work as expected.
22
23    A safe way to use the embedded SQL code in a C++ application is hiding
24    the ECPG calls in a C module, which the C++ application code calls into
25    to access the database, and linking that together with the rest of the
26    C++ code. See Section 34.13.2 about that.
27
28 34.13.1. Scope for Host Variables #
29
30    The ecpg preprocessor understands the scope of variables in C. In the C
31    language, this is rather simple because the scopes of variables is
32    based on their code blocks. In C++, however, the class member variables
33    are referenced in a different code block from the declared position, so
34    the ecpg preprocessor will not understand the scope of the class member
35    variables.
36
37    For example, in the following case, the ecpg preprocessor cannot find
38    any declaration for the variable dbname in the test method, so an error
39    will occur.
40 class TestCpp
41 {
42     EXEC SQL BEGIN DECLARE SECTION;
43     char dbname[1024];
44     EXEC SQL END DECLARE SECTION;
45
46   public:
47     TestCpp();
48     void test();
49     ~TestCpp();
50 };
51
52 TestCpp::TestCpp()
53 {
54     EXEC SQL CONNECT TO testdb1;
55     EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL CO
56 MMIT;
57 }
58
59 void Test::test()
60 {
61     EXEC SQL SELECT current_database() INTO :dbname;
62     printf("current_database = %s\n", dbname);
63 }
64
65 TestCpp::~TestCpp()
66 {
67     EXEC SQL DISCONNECT ALL;
68 }
69
70    This code will result in an error like this:
71 ecpg test_cpp.pgc
72 test_cpp.pgc:28: ERROR: variable "dbname" is not declared
73
74    To avoid this scope issue, the test method could be modified to use a
75    local variable as intermediate storage. But this approach is only a
76    poor workaround, because it uglifies the code and reduces performance.
77 void TestCpp::test()
78 {
79     EXEC SQL BEGIN DECLARE SECTION;
80     char tmp[1024];
81     EXEC SQL END DECLARE SECTION;
82
83     EXEC SQL SELECT current_database() INTO :tmp;
84     strlcpy(dbname, tmp, sizeof(tmp));
85
86     printf("current_database = %s\n", dbname);
87 }
88
89 34.13.2. C++ Application Development with External C Module #
90
91    If you understand these technical limitations of the ecpg preprocessor
92    in C++, you might come to the conclusion that linking C objects and C++
93    objects at the link stage to enable C++ applications to use ECPG
94    features could be better than writing some embedded SQL commands in C++
95    code directly. This section describes a way to separate some embedded
96    SQL commands from C++ application code with a simple example. In this
97    example, the application is implemented in C++, while C and ECPG is
98    used to connect to the PostgreSQL server.
99
100    Three kinds of files have to be created: a C file (*.pgc), a header
101    file, and a C++ file:
102
103    test_mod.pgc #
104           A sub-routine module to execute SQL commands embedded in C. It
105           is going to be converted into test_mod.c by the preprocessor.
106
107 #include "test_mod.h"
108 #include <stdio.h>
109
110 void
111 db_connect()
112 {
113     EXEC SQL CONNECT TO testdb1;
114     EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL CO
115 MMIT;
116 }
117
118 void
119 db_test()
120 {
121     EXEC SQL BEGIN DECLARE SECTION;
122     char dbname[1024];
123     EXEC SQL END DECLARE SECTION;
124
125     EXEC SQL SELECT current_database() INTO :dbname;
126     printf("current_database = %s\n", dbname);
127 }
128
129 void
130 db_disconnect()
131 {
132     EXEC SQL DISCONNECT ALL;
133 }
134
135    test_mod.h #
136           A header file with declarations of the functions in the C module
137           (test_mod.pgc). It is included by test_cpp.cpp. This file has to
138           have an extern "C" block around the declarations, because it
139           will be linked from the C++ module.
140
141 #ifdef __cplusplus
142 extern "C" {
143 #endif
144
145 void db_connect();
146 void db_test();
147 void db_disconnect();
148
149 #ifdef __cplusplus
150 }
151 #endif
152
153    test_cpp.cpp #
154           The main code for the application, including the main routine,
155           and in this example a C++ class.
156
157 #include "test_mod.h"
158
159 class TestCpp
160 {
161   public:
162     TestCpp();
163     void test();
164     ~TestCpp();
165 };
166
167 TestCpp::TestCpp()
168 {
169     db_connect();
170 }
171
172 void
173 TestCpp::test()
174 {
175     db_test();
176 }
177
178 TestCpp::~TestCpp()
179 {
180     db_disconnect();
181 }
182
183 int
184 main(void)
185 {
186     TestCpp *t = new TestCpp();
187
188     t->test();
189     return 0;
190 }
191
192    To build the application, proceed as follows. Convert test_mod.pgc into
193    test_mod.c by running ecpg, and generate test_mod.o by compiling
194    test_mod.c with the C compiler:
195 ecpg -o test_mod.c test_mod.pgc
196 cc -c test_mod.c -o test_mod.o
197
198    Next, generate test_cpp.o by compiling test_cpp.cpp with the C++
199    compiler:
200 c++ -c test_cpp.cpp -o test_cpp.o
201
202    Finally, link these object files, test_cpp.o and test_mod.o, into one
203    executable, using the C++ compiler driver:
204 c++ test_cpp.o test_mod.o -lecpg -o test_cpp