我想从VBA中的DLL获取整数值,如下面的代码。
double _stdcall pll_dll(double* datain0, double* datain1, double* dataout0, double* dataout1, BSTR * str, int* str_len)
{
char buff[128] = { 0 };
char * str0;
char str1[128] = { 0 };
int len;
*dataout0 = *datain0 + 20;
*dataout1 = *datain1 + 30;
len = 30;
*str_len = 30;
str0 = " Nice ";
sprintf(buff, "Hi %s \n", str0);
strcpy(str1, buff);
char* p = str1;
SysReAllocString(str, (OLECHAR*)p);
return 0;
}
VB
Private Declare PtrSafe Function pll_dll Lib "F:\work\pll_dll\x64\Debug\pll_dll.dll" _
(ByRef x_in As Double, ByRef y_in As Double, ByRef x_out As Double, ByRef y_out As Double, ByRef s As String, ByRef str_len As Integer) As Double
Dim s_len As Integer
Call pll_dll(3, 4, d1, d2, s, s_len)
但是我无法理解,当我在代码上面运行时,s_len在vba中始终为'0'。 但是另一个参数double * datain0,double * datain1,double * dataout0,double * dataout1,BSTR * str都运行良好。
有趣的事情,当我摆脱“BSTR * str”参数时 当我运行“double _stdcall pll_dll(double * datain0,double * datain1,double * dataout0,double * dataout1,int * str_len)”时,我也可以获得str_len 你可以让我知道我应该检查什么? 我怎样才能获得s_len值?答案 0 :(得分:3)
您滥用SysReAllocString()
。
你给它一个8位的ANSI字符串,它只是一个16位指针。它需要一个适当的16位Unicode字符串。如果你摆脱了类型转换,代码将无法编译,并且有充分的理由。不要使用类型转换来避免编译器错误。
您必须先将输出字符串数据转换为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;
len = 30;
*str_len = len;
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;
len = 30;
*str_len = len;
str0 = L" Nice ";
len = swprintf(buff, L"Hi %s \n", str0);
SysReAllocStringLen(str, buff, len);
return 0;
}