2017-03-17 44 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; 
    }