2012-09-07 39 views
0

我正在製作一個非託管的C++ DLL,它使用C#託管的DLL。我正在寫C++庫,因爲我需要使用可以作爲插件添加C++庫的軟件中定義的函數和頭文件。但是我想做的事情非常複雜,以致於我對C++的稀少知識會讓我放慢腳步,所以我決定在我最喜歡的C#中做一些事情,並通過COM連接這些DLL,並且我成功了。尋找最短的字符串類型轉換C++

我在編寫代碼時很成功,但在保持代碼簡潔方面不太成功,因爲我顯然不是專業的C++程序員。

問題是轉換各種字符串類型。 BSTR和特別是const char *。

以下代碼逆定理常量字符*到BSTR:

BSTR bstrt; 
const char * someChar; 

csharpInterfacedClassPointer->get_PropertyForSomeChars(&bstrt); 
strcpy_s(nstring, (char *)bstrt); 
someChar = nstring; 

的問題是,我有很多離散someChars與相應的離散接口方法...被從C#接口所以產生的屬性方法無法改變它。對於30個離散變量,每個「someChar」需要以下三行代碼,我需要編寫90行代碼。

csharpInterfacedClassPointer->get_PropertyForSomeCharX(&bstrt); 
strcpy_s(nstring, (char *)bstrt); 
someCharX = nstring; 

的問題是:你是怎麼寫的一些快捷鍵此所以它會只適合在一條線?

我用「getter」函數指針和someChar指針嘗試了某種函數。

但隨後編譯器說,一些奇怪的事情阿布德約束功能,以及它們是如何不允許作爲指針...我用Google搜索是什麼意思並給予所需的解決方案,以改變函數定義,但我不能這樣做是因爲定義是從C#代碼生成的(由regasm.exe生成)。

重要注意事項:我需要在最後得到const char *類型,因爲它是我爲其製作C++ DLL的程序的函數所需的輸入類型。

+0

我可以問你真的需要使用char數組而不是std:string(或者wstring)嗎?有定義的系統函數做從bstr轉換爲wstring,反之亦然(示例:http://stackoverflow.com/questions/6284524/bstr-to-stdstring-stdwstring-and-vice-versa) –

+0

不幸的是,我需要獲取字符串數組...由我編寫C++庫的程序函數施加的 – Mirek

+0

@Motig:'std :: string :: c_str()'問題已解決。 –

回答

0

這個問題可以如果任何國防部將要讀這被刪除。我意識到我有一個完全不同的問題。感謝Vagaus的努力。

1
Disclaimer: it was a long time (7 years to be more precise) since I have touched C++/COM code for the last time. 

關於將實例方法綁定到函數指針,請檢查此SO問題。

另一種選擇是使用IDispatch接口(如果您的COM組件實現它)

關於ConvertAndAssign()的實施,海事組織它有一些問題。爲了更容易地解釋,我已經波紋管抄了一遍:

void ConvertAndAssign(get_string_func bstr_get_fx, const char * constCharString) 
{ 
    const size_t nsize = 1000; 
    char nstring[nsize]; 

    BSTR bstrt; 
    bstrt = bstr_t(constCharString); // issue 1 
    bstr_get_fx(&bstrt); 
    strcpy_s(nstring, (char *)bstrt); // issue 2 
    constCharString = nstring; // issues 3 & 4 
} 
  1. 如果你的COM方法返回一個BSTR(即,它具有BSTR類型的輸出參數),你不應該在預先通過 - 分配的字符串,否則你會結束 泄漏內存。

  2. 鑄造bstr以char *將不起作用。 BSTR是Unicode字符串。它們也被編碼成其長度在實際字符之前。 如果您使用的是ATL/MFC,則可以使用string conversion macros之一。 如果您不使用ATL/MFC可以使用WideCharToMultiByte()功能或「智能」 BSTR類中的一個(的CComBSTR在ATL,bstr_t等)

  3. 分配nstringconstCharString將有沒有影響外部字符串。如果要調用ConvertAndAssign喜歡如下

    char *outsideStr = NULL;    
    ConvertAndAssign(whatever, outsideStr); 
    

    內ConvertAndAssign()函數consCharString將指向NULL在begning。 constCharString確實指向分配nstringoutsideStr後仍然指向NULL(請記住,當你叫ConvertAndAssign()函數指針值的副本傳遞給它)。

    爲了得到你想要的,你可以通過引用或指針的指針是什麼:

    void ConvertAndAssign(get_string_func bstr_get_fx, const char * &constCharString) 
    { 
         constCharString = nstring; // Assignment 
    } 
    

    或指針的指針:

    char *outsideStr = NULL; 
    ConvertAndAssign(whatever, &outsideStr); 
    
    void ConvertAndAssign(get_string_func bstr_get_fx, const char **constCharString) 
    { 
         . 
         . 
         . 
         *constCharString = nstring; // Assignment 
    } 
    
  4. 固定之前的後問題你會碰到另一個:你不能返回一個局部變量的地址!當您的代碼在ConvertAndAssign()返回後繼續執行時,此地址不會再分配給您(它是堆棧的一部分,所以它甚至可能會工作,但我向您保證,這不是;您的一點點變化 代碼可能會破壞它)

    要解決這個問題,你需要通過一個預先分配的字符串:

    char outsideStr[1000]; 
    ConvertAndAssign(whatever, outsideStr); 
    
    void ConvertAndAssign(get_string_func bstr_get_fx, const char * constCharString) 
    { 
        strcpy_s(constCharString, /* result str here */); 
    } 
    

    或分配在堆中的字符串。

鑑於所有上述情況,一種可能的實施ConvertAndAssign()和其用法如下:

char outsideStr[1000]; 
ConvertAndAssign(whatever, outsideStr); 

void ConvertAndAssign(get_string_func bstr_get_fx, const char * constCharString) 
{ 
    BSTR bstrt; 
    if(SUCCEEDED(bstr_get_fx(&bstrt))) 
    { 
     // Assumes constCharString points to a buffer large enough to hold the converted string. 
     strcpy_s(constCharString, CW2A(bstr)); // not completely correct since bstr may contain the byte 0 but I guess thats not your scenario. 
     SysFreeString(bstr); 
    } 
    else 
    { 
     // error handling. 
     constCharString[0] = 0; 
    } 
}