- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想从 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 : Hi Nice 儆儆儆儆儆儆儆儆좄* : String
最佳答案
您在滥用 SysReAllocString()
.
您的缓冲区在声明时未初始化,因此它们最初包含堆栈中已存在的任何随机字节。 sprintf()
和 strcpy()
然后用有效的 8 位数据填充缓冲区并以 null 终止它们,这在处理 8 位字符串时很好。但是它们不会覆盖空终止符之后的任何内存,因此那里仍然有随机字节。
然后您将按原样将最终的 8 位字符串数据提供给 SysReAllocString()
, 使用 char*
的简单类型转换指向 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;
}
关于c++ - 如何从 dll 中获取没有垃圾的字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42849095/
我是一名优秀的程序员,十分优秀!