2012-09-07 81 views
2

我想調用從OpenSSL庫此功能下面prototy定義:語義衝突傳遞指針爲const指針字節數組

X509 *d2i_X509(X509 **px, const unsigned char **in, int len); 

第二個參數in定義爲const unsigned char **因爲:

  • d2i_X509將不會修改由*in指向的緩衝區中的數據
  • *in將增加從數據分析的數據量 緩衝。

現在這個原型是一個問題,因爲據我所知,該函數不能被稱爲以下方式,據我所知,API是調用它的正常方式(錯誤管理代碼已刪除讓事情變得更簡單):

unsigned char buffer[2048]; 
unsigned char * end = buffer; 
unsigned char * p = buffer; 

end += read(fd, p, 2048); 
certlen1 = parseint(&p); 
X509 * cert1 = d2i_x509(NULL, &p, certlen1); 
certlen2 = parseint(&p); 
X509 * cert2 = d2i_x509(NULL, &p, certlen2); 

如果我嘗試編譯上面的代碼,它說:

error: invalid conversion from 'unsigned char**' to 'const unsigned char**' 

我理解消息的理由(解釋here例如),但在這種特殊情況下日基本原理不適用於它的文檔中的函數狀態,它只會增加值*in,不要爲它指派一個不相關的指針。

我不能改變p的類型爲const unsigned char *,因爲上面的代碼實際上是簡化的,指針隱藏在一些執行讀和寫的抽象IO對象後面。與以前的IO對象的好處是保持對稱的讀寫代碼在一起,可以使用兩個單獨的指針來讀寫我的IO對象,但總體上這樣做的好處是非常小(如果不是負數)並添加很多合成噪音。由於某些外部不相關的API調用而強迫IO對象發生這種深度內部變化,看起來真的很舒服。

解決方案可能是執行轉換,甚至根本不使用返回的指針值(因爲我有尺寸參數),但它也不會感覺正確。似乎d2i_X509的原型沒有包含足夠的信息,或者編譯器的const檢查規則在這種情況下過於嚴格。

如何從C++調用這樣的API?現在我只會使用演員陣容,因爲我覺得這是一個較小的邪惡,但有沒有更好的辦法?

回答

1

首先,在此代碼+=沒有多大意義:

p += read(fd, p, 2048); 

你修改p指向剛剛過去你剛纔讀的數據,所以d2i_x509會閱讀垃圾。

我會做這樣的:

unsigned char buffer[2048]; 
int n = read(fd, buffer, 2048); 
if (n < 0) ..error..; 
const unsigned char * p = buffer; 
X509 * cert1 = d2i_x509(NULL, &p, certlen1); 
X509 * cert2 = d2i_x509(NULL, &p, certlen2); 
int used = p - buffer; // # of bytes actually parsed by the two calls 

未來發生的變化可以做buffer直接。

編輯:

確定,然後替換此:

X509 * cert1 = d2i_x509(NULL, &p, certlen1); 

與此:

{ 
    const unsigned char *q = p; 
    X509 * cert1 = d2i_x509(NULL, &q, certlen1); 
    p += q - p; 
} 
+0

你在技術上是正確的,但完全除點,雖然過於simplyfing我的實際代碼,我有點過頭了。實際上,我有第二個指針'end',它是通過讀取遞增的,certlen1和certlen2是用p從緩衝區開始解析和提取的,並且沿着方向遞增。另外,p存儲在一些不透明的對象中,這些對象在緩衝區上執行讀取和寫入操作,並(檢查邊界)。雖然可能使內部p常量是一個真正的負擔,沒有明確的好處。換句話說,如果它是玩具而不是真正的程序,那麼建議的提議將是可能的。 – kriss

+0

我並不確定它比演員表更好(看起來像是對常規檢查系統犯規的方式),但是這絕對是避免投射的一種可能的解決方案。 – kriss