35.13. ÐÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° C++ #
ECPG обеÑпеÑÐ¸Ð²Ð°ÐµÑ Ð¿Ð¾Ð´Ð´ÐµÑÐ¶ÐºÑ ÑзÑка C++ в огÑаниÑенном обÑÑме. ÐекоÑоÑÑе ÐµÑ Ð¾ÑобенноÑÑи опиÑÐ°Ð½Ñ Ð² ÑÑом Ñазделе.
ÐÑепÑоÑеÑÑÐ¾Ñ ecpg пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð²Ñ
одной Ñайл, напиÑаннÑй на C (или ÑзÑке, подобном C) Ñо вÑÑÑаиваемÑми командами SQL, пÑеобÑазÑÐµÑ Ð²ÑÑÑоеннÑе ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL в конÑÑÑÑкÑии ÑзÑка C и в ÑезÑлÑÑаÑе ÑоÑмиÑÑÐµÑ Ñайл .c. ÐбÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾ÑеÑнÑÑ
ÑÑнкÑий, вÑзÑваемÑÑ
в конÑÑÑÑкÑиÑÑ
C, коÑоÑÑе генеÑиÑÑÐµÑ ecpg, завоÑаÑиваÑÑÑÑ Ð² блоки extern "C" { ... } пÑи иÑполÑзовании C++, Ñак ÑÑо они Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑозÑаÑно ÑабоÑаÑÑ Ð² C++.
Ðднако вообÑе говоÑÑ, пÑепÑоÑеÑÑÐ¾Ñ ecpg Ð¿Ð¾Ð½Ð¸Ð¼Ð°ÐµÑ ÑолÑко C; он не воÑпÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð¾ÑобÑй ÑинÑакÑÐ¸Ñ Ð¸ заÑезеÑвиÑованнÑе Ñлова ÑзÑка C++. ÐоÑÑÐ¾Ð¼Ñ ÐºÐ°ÐºÐ¾Ð¹-Ñо код SQL, вÑÑÑоеннÑй в код пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° C++, в коÑоÑом иÑполÑзÑÑÑÑÑ ÑложнÑе оÑобенноÑÑи C++, Ð¼Ð¾Ð¶ÐµÑ ÐºÐ¾ÑÑекÑно не обÑабоÑаÑÑÑÑ Ð¿ÑепÑоÑеÑÑоÑом или не ÑабоÑаÑÑ ÐºÐ°Ðº ожидаеÑÑÑ.
ÐадÑжнÑй Ð¿Ð¾Ð´Ñ Ð¾Ð´ к пÑÐ¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð½ÐµÐ´ÑÑнного кода SQL в пÑиложении на C++ заклÑÑаеÑÑÑ Ð² Ñом, ÑÑÐ¾Ð±Ñ ÑкÑÑÑÑ Ð²ÑÐ·Ð¾Ð²Ñ ECPG в модÑле C, коÑоÑÑй бÑÐ´ÐµÑ Ð²ÑзÑваÑÑÑÑ Ð¿Ñиложением на C++ Ð´Ð»Ñ ÑабоÑÑ Ñ Ð±Ð°Ð·Ð¾Ð¹ даннÑÑ Ð¸ коÑоÑÑй бÑÐ´ÐµÑ Ñкомпонован Ñ Ð¾ÑÑалÑнÑм кодом C++. ÐодÑобнее ÑÑо опиÑано в ÐодÑазделе 35.13.2.
35.13.1. ÐблаÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи пеÑеменнÑÑ ÑÑÐµÐ´Ñ #
ÐÑепÑоÑеÑÑÐ¾Ñ ecpg Ð¸Ð¼ÐµÐµÑ Ð¿Ð¾Ð½Ð¸Ð¼Ð°Ð½Ð¸Ðµ облаÑÑи видимоÑÑи пеÑеменнÑÑ
в C. С ÑзÑком C ÑÑо доволÑно пÑоÑÑо, Ñак как облаÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи пеÑеменнÑÑ
опÑеделÑеÑÑÑ Ð¸Ñ
блоками кода. Ð C++, однако, пеÑеменнÑе-ÑÐ»ÐµÐ½Ñ ÐºÐ»Ð°ÑÑа задейÑÑвÑÑÑÑÑ Ð½Ðµ в Ñом блоке кода, в каком они обÑÑвленÑ, Ñак ÑÑо пÑепÑоÑеÑÑÐ¾Ñ ecpg не ÑÐ¼Ð¾Ð¶ÐµÑ ÐºÐ¾ÑÑекÑно опÑеделиÑÑ Ð¾Ð±Ð»Ð°ÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи ÑакиÑ
пеÑеменнÑÑ
.
ÐапÑимеÑ, в ÑледÑÑÑем ÑлÑÑае пÑепÑоÑеÑÑÐ¾Ñ ecpg не ÑÐ¼Ð¾Ð¶ÐµÑ Ð½Ð°Ð¹Ñи опÑеделение пеÑеменной dbname в меÑоде test, Ñак ÑÑо пÑоизойдÑÑ Ð¾Ñибка.
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;
}ÐÑи обÑабоÑке данного кода бÑÐ´ÐµÑ Ð²Ñдано ÑообÑение:
ecpg test_cpp.pgc
test_cpp.pgc:28: ERROR: variable "dbname" is not declared
(test_cpp.pgc:28: ÐШÐÐÐÐ: пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ "dbname" не обÑÑвлена)
ÐÐ»Ñ ÑеÑÐµÐ½Ð¸Ñ ÑÑой пÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ немного измениÑÑ Ð¼ÐµÑод test и задейÑÑвоваÑÑ Ð² нÑм локалÑнÑÑ Ð¿ÐµÑеменнÑÑ Ð´Ð»Ñ Ð¿ÑомежÑÑоÑного Ñ
ÑанениÑ. Ðо пÑедложеннÑй подÑ
од нелÑÐ·Ñ ÑÑиÑаÑÑ Ñ
оÑоÑим, Ñак как ÑÑо поÑÑÐ¸Ñ ÐºÐ¾Ð´ и ÑÐ½Ð¸Ð¶Ð°ÐµÑ Ð¿ÑоизводиÑелÑноÑÑÑ.
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);
}35.13.2. РазÑабоÑка пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° C++ Ñ Ð²Ð½ÐµÑним модÑлем на C #
ÐÑли Ð²Ñ Ð¿Ð¾Ð½Ñли ÑеÑ
ниÑеÑкие огÑаниÑÐµÐ½Ð¸Ñ Ð¿ÑепÑоÑеÑÑоÑа ecpg Ñ C++, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе пÑийÑи к заклÑÑениÑ, ÑÑо Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ECPG в пÑиложениÑÑ
на C++ лÑÑÑе ÑвÑзÑваÑÑ ÐºÐ¾Ð´ C Ñ ÐºÐ¾Ð´Ð¾Ð¼ C++ на ÑÑадии компоновки, а не внедÑÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL непоÑÑедÑÑвенно в код на C++. Рданном Ñазделе показÑваеÑÑÑ, как оÑделиÑÑ Ð²ÑÑÑаиваемÑе ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL Ð¾Ñ ÐºÐ¾Ð´Ð° пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° C++, на пÑоÑÑом пÑимеÑе. Ð ÑÑом пÑимеÑе пÑиложение ÑеализÑеÑÑÑ Ð½Ð° C++, а взаимодейÑÑвие Ñ ÑеÑвеÑом Postgres Pro поÑÑÑоено на C и ECPG.
ÐÐ»Ñ ÑбоÑки нÑжно ÑоздаÑÑ ÑÑи Ñипа Ñайлов: Ñайл на C (*.pgc), заголовоÑнÑй Ñайл и Ñайл на C++:
test_mod.pgc#ÐодÑÐ»Ñ Ð¿Ð¾Ð´Ð¿ÑогÑамм бÑÐ´ÐµÑ Ð²ÑполнÑÑÑ SQL-командÑ, вÑÑÑоеннÑе в C. ÐÑÐ¾Ñ ÐºÐ¾Ð´ нÑжно бÑÐ´ÐµÑ Ð¿ÑеобÑазоваÑÑ Ð²
test_mod.cÑ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¿ÑепÑоÑеÑÑоÑа.#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; EXEC SQL SELECT current_database() INTO :dbname; printf("current_database = %s\n", dbname); } void db_disconnect() { EXEC SQL DISCONNECT ALL; }test_mod.h#ÐаголовоÑнÑй Ñайл Ñ Ð¾Ð±ÑÑвлениÑми ÑÑнкÑий в модÑле на ÑзÑке C (
test_mod.pgc). Ðн вклÑÑаеÑÑÑ Ð²test_cpp.cpp. ÐбÑÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð² ÑÑом Ñайле Ð´Ð¾Ð»Ð¶Ð½Ñ Ð·Ð°ÐºÐ»ÑÑаÑÑÑÑ Ð² блокextern "C", Ñак как он бÑÐ´ÐµÑ ÑвÑзÑваÑÑÑÑ Ñ Ð¼Ð¾Ð´Ñлем C++.#ifdef __cplusplus extern "C" { #endif void db_connect(); void db_test(); void db_disconnect(); #ifdef __cplusplus } #endiftest_cpp.cpp#ÐÑновной код пÑиложениÑ, ÑодеÑжаÑий ÑÑнкÑиÑ
main, а Ñакже, в данном пÑимеÑе, клаÑÑ C++.#include "test_mod.h" class TestCpp { public: TestCpp(); void test(); ~TestCpp(); }; TestCpp::TestCpp() { db_connect(); } void TestCpp::test() { db_test(); } TestCpp::~TestCpp() { db_disconnect(); } int main(void) { TestCpp *t = new TestCpp(); t->test(); return 0; }
ÐÐ»Ñ ÑбоÑки пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿ÑоделайÑе ÑледÑÑÑее. ÐÑеобÑазÑйÑе test_mod.pgc в test_mod.c Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ecpg, а заÑем полÑÑиÑе test_mod.o, ÑкомпилиÑовав test_mod.c компилÑÑоÑом C:
ecpg -o test_mod.c test_mod.pgc cc -c test_mod.c -o test_mod.o
ÐоÑле ÑÑого полÑÑиÑе test_cpp.o, ÑкомпилиÑовав test_cpp.cpp компилÑÑоÑом C++:
c++ -c test_cpp.cpp -o test_cpp.o
ÐаконеÑ, ÑвÑжиÑе полÑÑеннÑе обÑекÑнÑе ÑайлÑ, test_cpp.o и test_mod.o, в один иÑполнÑемÑй Ñайл, вÑполнив ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²ÐºÑ Ð¿Ð¾Ð´ ÑпÑавлением компилÑÑоÑа C++:
c++ test_cpp.o test_mod.o -lecpg -o test_cpp