2017-03-17 70 views
0

我想擺脫在VB DLL中的字符串,所以我做了一些代碼下面,如何從dll中獲取沒有垃圾的字符串?

#include <windows.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <iostream> 
#include <tchar.h> 
#include <atlconv.h> 
#include <atlcoll.h> 
#include <assert.h> 
#include <atlbase.h> 

using namespace std; 

double _stdcall pll_dll(double* datain0, double* datain1, double* dataout0, double* dataout1, BSTR * str, int* str_len) 
{ 
    char buff[128]; 
    char * str0; 
    char str1[128]; 


    *dataout0 = *datain0 + 20; 
    *dataout1 = *datain1 + 30; 

    *str_len = 30; 

    str0 = " Nice "; 
    sprintf(buff, "Hi %s \n", str0); 
    strcpy(str1, buff); 

    char* p = str1; 
    SysReAllocString(str, (OLECHAR*)p); 



    return 0; 
} 

但是,尤其是,在這種情況下,當我證明S,我有一個包含垃圾數據的字符串,如下所示。

那麼我怎樣才能得到沒有這個垃圾數據的字符串?

:S:嗨尼斯儆儆儆儆儆儆儆儆좄*:字符串

回答

1

你濫用SysReAllocString()

您的緩衝區在聲明時未初始化,因此它們最初包含堆棧中已存在的任何隨機字節。 sprintf()strcpy()然後用有效的8位數據填充緩衝區,並將它們終止爲零,這對於處理8位字符串時很好。但是它們不會覆蓋超過空終止符的任何內存,所以仍然存在隨機字節。

然後,您將最終的8位字符串數據原樣提供給SysReAllocString(),使用char*指針的簡單類型轉換指針指向wchar_t*指針以保持編譯器的快樂。但是你仍然指向8位數據。 SysReAllocString()需要一個適當的16位Unicode字符串,包括一個16位的null終止符。由於您只有一個8位的空終止符,函數最終會將您的空終止符複製到周圍的內存中。

如果你擺脫了類型轉換,代碼將無法編譯,並有很好的理由。不要使用類型轉換來避免編譯錯誤。

用零預初始化緩衝區將只會掩蓋問題,確保最終緩衝區中有連續的空字節,當解釋爲16位數據時,可以充當Unicode空終止符。但是您仍然在緩衝區中存儲8位字符數據以開始。

要正確地解決此問題,您必須先將輸出字符串數據轉換爲Unicode,然後才能從中創建BSTR

您需要:

  • 使用MultiByteToWideChar()到您的最終char數據轉換爲wchar_t

    double _stdcall pll_dll(double* datain0, double* datain1, double* dataout0, double* dataout1, BSTR * str, int* str_len) 
    { 
        char c_buff[128] = {0}; 
        wchar_t w_buff[128] = {0}; 
        char * str0; 
        int len; 
    
        *dataout0 = *datain0 + 20; 
        *dataout1 = *datain1 + 30; 
    
        *str_len = 30; 
    
        str0 = " Nice "; 
        len = sprintf(c_buff, "Hi %s \n", str0); 
    
        len = MultiByteToWideChar(CP_ACP, 0, c_buff, len, w_buff, 128); 
    
        SysReAllocStringLen(str, w_buff, len); 
    
        return 0; 
    } 
    
  • 重寫使用swprintf()代替sprintf()的代碼。

    double _stdcall pll_dll(double* datain0, double* datain1, double* dataout0, double* dataout1, BSTR * str, int* str_len) 
    { 
        wchar_t buff[128] = {0}; 
        wchar_t * str0; 
        int len; 
    
        *dataout0 = *datain0 + 20; 
        *dataout1 = *datain1 + 30; 
    
        *str_len = 30; 
    
        str0 = L" Nice "; 
        len = swprintf(buff, L"Hi %s \n", str0); 
    
        SysReAllocStringLen(str, buff, len); 
    
        return 0; 
    }