如何从 dll 获取没有垃圾的字符串?
How can I get a string without garbage from dll?
我想从 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 : 嗨尼斯儆儆儆좄* : 字符串
您滥用了SysReAllocString()
。
缓冲区在声明时未初始化,因此它们最初包含堆栈上已存在的任何随机字节。 然后sprintf()
和strcpy()
用有效的 8 位数据填充缓冲区并终止它们,这在处理 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; }
- Visual c ++,使用字符串引用/指针调用 dll 函数
- 从DLL导出函数,LoadLibrary()需要用TEXT转换的字符串才能编译而不会出错
- 如何将 VB.Net 字符串作为字符*传递给C++dll?
- C# 和 C++ dll - 封送字符串
- 为什么在调用C#DLL时不需要提供字符串缓冲区
- 随机字符,从强制转换 Arduino 字符串到 Excel BSTR 通过 c++ DLL
- Java 调用 dll 字符串返回类型方法
- 如何在 VBA/Excel 中创建字符串数组并将其发送到C++ DLL,以便可以在 DLL 中循环访问它
- 将字符串向量从 C# 传递到C++ DLL
- 使用 DLL 在 c++ 和 C# 之间交换字符串
- 为什么 C# 封送字符串不适用于C++ DLL
- C++中具有"::"字符串名称的 DLL 导出调用
- 放置在外部 DLL 中的类中的字符串数据的内存损坏
- 从 dll 返回多个字符串
- 将字符串从 C# 发送到 dll 文件C++
- 从dll传递c字符串,穿过外部C
- 如何将字符串从C++DLL返回到MetaTrader 4代码执行生态系统?
- 将字符串[]从C#发送到SafeArrayAccessData()上的C++ Dll 'E_UNEXPECTEDCatastrophic Error'
- 编译时如何隐藏DLL文件中的字符串?
- 将C#中的C++类与字符串(Dll)一起使用