PostgreSQL C++ 應(yīng)用

2021-09-02 14:53 更新
35.13.1. 主變量的可見(jiàn)范圍
35.13.2. 使用外部 C 模塊的 C++ 應(yīng)用開(kāi)發(fā)

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é)。

35.13.1. 主變量的可見(jiàn)范圍

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);
}

35.13.2. 使用外部 C 模塊的 C++ 應(yīng)用開(kāi)發(fā)

如果你理解了 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)行ecpgtest_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.otest_mod.o)成為一個(gè)可執(zhí)行文件:

c++ test_cpp.o test_mod.o -lecpg -o test_cpp


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)