Reputation: 495
I am trying to send a BSTR string written in a C DLL to Excel.
Problem:
Excel VBA receives the BSTR from the C DLL. I can see the BSTR in the VBA Intermediate window and debug window.
If I try to allocate this string to a cell within a sheet, the value within the cell is the first letter of the string ("S").
It seems that when I try to allocate a cell with the value of the BSTR, it is using a pointer to the start of the String. I do not know how to show the whole BSTR string.
C Code:
BSTR _stdcall ReturnString(void)
{
return SysAllocString(L"String From DLL");
}
VBA Code:
Private Declare Function ReturnString Lib "C:\ex4dl.dll" () As String
Sub test_sub()
Dim result As String
result = ReturnString()
Range("B1").Value = result
Debug.Print result
End Sub
Following on from my comment that the C function works ok if called directly from a cell and StrConv() not working as a complete fix, below is the C code for the concatenated strings.
C Code:
BSTR _stdcall ReturnStringTwo(BSTR stringOne, BSTR stringTwo )
{
BSTR finalString;
int buffer_len = _snwprintf(0,0,L"The strings that was passed (%s) and (%s)", stringOne, stringTwo);
finalString = SysAllocStringLen(0, buffer_len);
_snwprintf(finalString,buffer_len,L"The strings that was passed (%s) and (%s)", stringOne, stringTwo);
return finalString;
}
VBA Code:
Private Declare Function ReturnStringTwo Lib "C:\ex4dl.dll" (ByVal stringOne As String, ByVal stringTwo As String) As String
Sub test_sub()
Dim iString As String
Dim iStringTwo As String
Dim one As String
Dim two As String
one = "One"
two = "Two"
iString = ReturnString()
iStringTwo = ReturnStringTwo(one, two)
Range("B1").Value = StrConv(iString, vbFromUnicode) ' Works ok with the C only string'
Range("B2").Value = StrConv(iStringTwo, vbFromUnicode) 'Does not work correctly. The cells value is: "The strings that was passed (?e) and (?o)"'
End Sub
Both functions work if called directly from a cell, but not if allocated to a cell.value from VBA.
[Excel 2010 32bit]
Upvotes: 2
Views: 993
Reputation: 304
I found the solution in the comment by simply re-creates an array in VBA with StrConv(result, vbFromUnicode) converting value in the output. That solved the problem. Here is my VBA code:
Public Function apiCall(x As Range) As Variant
Dim selectedArray As Variant
selectedArray = x.Value2
Dim dll_output(32, 32) As String
Dim res(32, 32) As String
v = callDllFunc(selectedArray, dll_output)
For j = LBound(dll_output, 2) To UBound(dll_output, 2)
For i = LBound(dll_output, 1) To UBound(dll_output, 1)
res(i, j) = StrConv(dll_output(i, j), vbFromUnicode)
Next
Next
apiCall = res
End Function
Note that the code above simply creates an 32x32 double String array. You might need to adjust the size by yourself. I hope that this helps!
Upvotes: 1