W3Cschool
恭喜您成為首批注冊(cè)用戶(hù)
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
ECPG 對(duì)于 C++ 應(yīng)用提供了有限的支持。這一節(jié)描述了一些忠告。
ecpg
預(yù)處理器采用一個(gè)用 C(或者類(lèi)似 C 的東西)和嵌入式 SQL 命令編寫(xiě)的輸入文件,把嵌入式 SQL 命令轉(zhuǎn)換成 C 語(yǔ)言塊,并且最終產(chǎn)生一個(gè).c
文件。在 C++ 下使用時(shí),因此它們應(yīng)該能在 C++ 中無(wú)縫地使用。
不過(guò),通常ecpg
預(yù)處理器只理解 C,它無(wú)法處理 C++ 語(yǔ)言的特殊語(yǔ)法和保留詞。因此,一些寫(xiě)在 C++ 應(yīng)用代碼中的使用了 C++ 特定復(fù)雜特性的嵌入式 SQL 代碼可能無(wú)法被正確地預(yù)處理或者無(wú)法按預(yù)期工作。
使用 C++ 應(yīng)用中嵌入式 SQL 代碼的安全方法是把 ECPG 調(diào)用隱藏在一個(gè) C 模塊中,C++ 應(yīng)用代碼會(huì)調(diào)用它來(lái)訪問(wèn)數(shù)據(jù)庫(kù),還要把它和剩余的 C++ 代碼鏈接起來(lái)。詳見(jiàn)第 35.13.2 節(jié)。
ecpg
預(yù)處理器能理解 C 中變量的可見(jiàn)范圍。在 C 語(yǔ)言中,這是相當(dāng)簡(jiǎn)單的,因?yàn)樽兞康目梢?jiàn)范圍是基于它們的代碼塊的。不過(guò)在 C++ 中,引用類(lèi)成員變量的代碼塊是不同于定義它的代碼塊的,因此ecpg
預(yù)處理器將無(wú)法理解類(lèi)成員變量的可見(jiàn)范圍。
例如,在下面的情況中,ecpg
預(yù)處理器無(wú)法為test
方法中的變量dbname
找到任何生命,因此將發(fā)生一個(gè)錯(cuò)誤。
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;
}
這段代碼將導(dǎo)致一個(gè)這樣的錯(cuò)誤:
ecpg test_cpp.pgc
test_cpp.pgc:28: ERROR: variable "dbname" is not declared
為了避免這種可見(jiàn)性問(wèn)題,可以修改test
方法來(lái)把一個(gè)本地變量用作中間存儲(chǔ)。但是這種方法只是一種比較差的變通方案,因?yàn)樗尨a變得丑陋并且降低了性能。
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);
}
如果你理解了 C++ 中ecpg
預(yù)處理器的這些技術(shù)限制,你可能已經(jīng)知道在鏈接階段把 C 對(duì)象和 C++ 對(duì)象鏈接起來(lái)讓 C++ 應(yīng)用能使用 ECPG 特性比直接在 C++ 代碼中寫(xiě)一些嵌入式 SQL 命令要更好。這一節(jié)用一個(gè)簡(jiǎn)單的例子描述了一種將嵌入式 SQL 命令從 C++ 應(yīng)用代碼中獨(dú)立出去的方法。在這個(gè)例子中,應(yīng)用由 C++ 實(shí)現(xiàn),而 C 和 ECPG 被用來(lái)連接到 PostgreSQL 服務(wù)器。
需要?jiǎng)?chuàng)建三種文件:一個(gè) C 文件(*.pgc
)、一個(gè)頭文件和一個(gè) C++ 文件:
test_mod.pgc
一個(gè)執(zhí)行嵌入在 C 中的 SQL 命令的子例程模塊。它將被預(yù)處理器轉(zhuǎn)換成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
)中函數(shù)定義的頭文件。它會(huì)被test_cpp.cpp
包括。這個(gè)文件必須在聲明周?chē)幸粋€(gè)extern "C"
塊,因?yàn)樗鼘⒈绘溄拥?C++ 模塊。
#ifdef __cplusplus
extern "C" {
#endif
void db_connect();
void db_test();
void db_disconnect();
#ifdef __cplusplus
}
#endif
test_cpp.cpp
應(yīng)用的主代碼,包括main
例程以及這個(gè)例子中的一個(gè) C++ 類(lèi)。
#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;
}
要構(gòu)建該應(yīng)用,按以下步驟處理。通過(guò)運(yùn)行ecpg
將test_mod.pgc
轉(zhuǎn)換為test_mod.c
,并且用 C 編譯器將test_mod.c
編譯成test_mod.o
:
ecpg -o test_mod.c test_mod.pgc
cc -c test_mod.c -o test_mod.o
接著,用 C++ 編譯器把test_cpp.cpp
編譯成test_cpp.o
:
c++ -c test_cpp.cpp -o test_cpp.o
最后,使用 C++ 編譯器鏈接這些對(duì)象文件(test_cpp.o
和test_mod.o
)成為一個(gè)可執(zhí)行文件:
c++ test_cpp.o test_mod.o -lecpg -o test_cpp
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: