简体   繁体   English

如何从dll中获取没有垃圾的字符串?

[英]How can I get a string without garbage from dll?

I'd like to get a string from dll in the VB so I've made some code as the below, 我想从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;
}

But especially, in this case, when I prove the s, I've got a string with garbage data as the below. 但是特别是在这种情况下,当我证明s时,我得到了一个包含垃圾数据的字符串,如下所示。

So how can I get a string without this garbage data? 那么,如何在没有此垃圾数据的情况下获得字符串?

: s : Hi Nice 儆儆儆儆儆儆儆儆좄* : String :s:嗨尼斯儆儆儆儆儆儆儆儆좄*:字符串

You are misusing SysReAllocString() . 您正在滥用SysReAllocString()

Your buffers are uninitialized when declared, so they initially contain whatever random bytes already existed on the stack. 缓冲区在声明时未初始化,因此它们最初包含堆栈上已经存在的任何随机字节。 sprintf() and strcpy() then populate the buffers with valid 8-bit data and null terminate them, which is fine when working with 8-bit strings. sprintf()strcpy()使用有效的8位数据填充缓冲区,并以null终止它们,这在使用8位字符串时很好。 But they don't overwrite any memory past the null terminators, so there is still random bytes located there. 但是它们不会覆盖空终止符之后的任何内存,因此仍然存在随机字节。

You are then giving the final 8-bit string data as-is to SysReAllocString() , using a simple typecast of a char* pointer to a wchar_t* pointer to keep the compiler happy. 然后,使用char*指针到wchar_t*指针的简单类型转换,将最终的8位字符串数据原样提供给SysReAllocString() ,以使编译器满意。 But you are still pointing at 8-bit data. 但是您仍然指向8位数据。 SysReAllocString() expects a proper 16-bit Unicode string instead, including a 16-bit null teminator. SysReAllocString()期望使用正确的16位Unicode字符串,包括16位null终止符。 Since you only have an 8-bit null terminator, the function ends up copying past your null terminator into surrounding memory. 由于您只有8位的空终止符,因此该函数最终将空终止符复制到周围的内存中。

If you get rid of the typecast, the code would fail to compile, and for good reason. 如果您摆脱了类型转换,则代码将无法编译,这是有充分理由的。 Don't use typecasts to avoid compiler errors. 不要使用类型转换来避免编译器错误。

Pre-initializing the buffers with zeros will only mask the problem, by ensuring there are consecutive null bytes in the final buffer that can act as a Unicode null terminator when interpreted as 16-bit data. 通过确保最终缓冲区中存在连续的空字节(当解释为16位数据时可以充当Unicode空终止符),用0预先初始化缓冲区将仅掩盖该问题。 But you are still storing 8-bit character data in the buffers to begin with. 但是,您仍然将8位字符数据存储在缓冲区中。

To properly fix this, you must convert your output string data to Unicode before you can then create a BSTR from it. 要正确解决此问题,必须先将输出字符串数据转换为Unicode,然后才能从中创建BSTR

You need to either: 您需要:

  • use MultiByteToWideChar() to convert your final char data to wchar_t . 使用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; } 
  • rewrite the code to use swprintf() instead of sprintf() . 重写代码以使用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; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM