2012-01-25 67 views
6

這是一個完全重寫的版本an earlier question;我認爲第一個版本省略了重要細節;這個提供了所有的上下文。C/C++ API難題

我有一些C++ API的頭文件。 API聲明幾個這樣的類:

class Foo 
{ 
public: 
    inline void Bar(void); 
    /* more inlines */ 
private: 
    inline Foo(); 
    /* maybe more inline constructors */ 
} 

即,沒有成員,所有函數都是內聯和公共的,除了構造函數。構造函數是私有的,所以,據我瞭解C++,我不能真正地調用它們。要創建這些對象,我應該使用auto_ptr s到他們:

class FooAutoPtr : public std::auto_ptr<Foo> 
{ 
public: 
    inline FooAutoPtr(); 
    /* one for each Foo constructors */ 
} 

的API也有這樣的第二套操作:

void Foo_Bar(void *self); 
Foo* Foo_Constructor(); 

讓我們稱他們爲核心功能,因爲這些是從主機應用程序實際導出的符號。不是C++類。核心函數具有C鏈接(即它們被聲明爲extern "C"),但是它們被聲明爲接受和返回C++類型(例如,它們可以引用:Foo &foo)。最後,頭文件包含了C++類的內聯函數的實現。所有這些功能都是一樣的:他們稱之爲核心功能。例如,FooAutoPtr構造是這樣的:

inline FooAutoPtr::FooAutoPtr() 
{ 
    reset(Foo_Constructor()); 
} 

據我所知,代碼從主機應用程序接收應該是一個指向某個對象,以Foo和改變auto_ptr Gizmo將指向這個對象。但對開發者來說,它看起來好像是一個指向Foo的真實指針。並呼籲Foo::Bar()是這樣的:

inline Foo::Bar() 
{ 
    Foo_Bar(this); 
} 

這同樣適用於所有的C++的類和方法。聰明吧?

現在有人能解釋一下這是什麼意思? :)它不是一個真正的C++ API,是嗎?對我來說,它看起來更像是一個C++封裝的C++封裝。如果是這樣,可以重新聲明核心函數丟失C++位?我知道如何編寫一個圍繞C++的C封裝(實際上,我已經寫過),但是,如果可能的話,我寧願丟失封裝並直接使用函數。但是,我如何失去C++的東西?

例如,有可能是參考文獻的功能:

Bar& Foo_GetBar(void* self, const Baz& baz, int& i); 

現在我把它從我的C++包裝是這樣的:

typedef struct bar bar_t; /* and others */ 
/*...*/ 
bar_t* 
foo_get_bar(foo_t* foo, baz_t* baz, int* i) 
{ 
    return (bar_t*) &Foo_GetBar(foo, *(Baz*)baz, *i); 
} 

和它的工作(我不知道,怎麼樣)。但我寧願把它重新聲明是這樣的:

/* type? */ Foo_GetBar(foo_t*, /* type? /*, /* type? */); 

更新:我發現證實Neil's answer一件有趣的事情。 Common Lisp中的代碼使用相同的API。 (當然,它必須使用C部分。)而且,從我可以(幾乎)讀取的源代碼中,作者只是使用指針代替引用。以下是將C++聲明轉換爲Lisp的代碼片段:

;; use * instead of & - we're not interested in C++ details 
line (regex-replace-all "&" line "*") 

這就是它:)謝謝大家!

+8

哇,這是一個問題,這是一個問題'_'和'C++'_legitimately_標記。一種罕見的外觀...... – ildjarn

+2

如果核心函數返回C++類型(引用),那麼它是真正的實時C++ API(不是C API),但它不是面向對象的。 –

+0

@SethCarnegie就這樣:)你看,頭部甚至在覈心函數附近有一條評論,說這些是「僅限C的環境」。那麼,另一個過時的評論:) –

回答

4

理論上,編譯器如何在C-linkage聲明中處理引用的細節是未指定的實現細節。然而,許多編譯器將它視爲指針。因此,如果C++庫頭文件導入Bar& Foo_GetBar(void* self, const Baz& baz, int& i);,那麼您可以嘗試將它導入到C頭文件中,作爲bar_t* Foo_GetBar(foo_t* self, const baz_t* baz, int* i);,它可能正常工作。

+0

我會試試看。我懷疑這樣的事情,但沒有確認就沒有勇氣開始:)謝謝! –

+0

順便說一句,我更新了關於Lisp代碼的文章,我剛剛發現使用相同的API,是的,它只是使用指針:)所以你是對的。 –

1
#define & * // convert references into pointers. 

停止。對。那裏。這只是一個笑話,而不是試圖看看在單個答案中可以累積多少個積極報酬。

但是重寫頭文件來替換引用指針的方法當然應該起作用。因爲這些都是C函數,所以沒有名字可以擔心,我還沒有看到一個不會將引用實現爲指針的編譯器。 (是否有其他可能的方法?)

+0

'#define'只能用於標識符,所以你不能這樣做: –

+0

@Seth:的確如此。這也是一樣,真的。 – Roddy