我想在VB中从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:嗨好儆儆儆儆儆儆儆좄*:字符串
答案 0 :(得分:1)
您滥用SysReAllocString()
。
您的缓冲区在声明时未初始化,因此它们最初包含堆栈中已存在的任何随机字节。 sprintf()
和strcpy()
然后使用有效的8位数据填充缓冲区并使用null终止它们,这在使用8位字符串时很好。但它们不会覆盖空终止符之后的任何内存,因此那里仍然存在随机字节。
然后使用SysReAllocString()
指向char*
指针的简单类型转换,将最终的8位字符串数据按原样提供给wchar_t*
,以保持编译器满意。但是你仍然指着8位数据。 SysReAllocString()
需要一个正确的16位Unicode字符串,包括一个16位的空终止符号。由于您只有一个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;
}