dvplayltd
asked on
How to get correct string return from C DLL ?
Hi experts!
I make a call from Vb6 to DLL written in MS C. I get result in sErr without get error, but I can see all message only in Intermediate windows of Vb6. When I make for example msgbox sErr I get only first letter of whole text. Review pic. To understand better situation.
I have a row sErr = String(255, vbNullChar) which is not seen by the picture, but this doesn’t help.
Please help – how to get this text in ordinary VB6 string ?
Thanks.
P.S: here you describe what is result of function from C declaration
7.2 GetErrorText()
const char* GetErrorText(int nError) const;
Return: The GetErrorText() function returns a pointer to a character string that contains a printable version of the error indicated by nError.
String-Mistery.png
I make a call from Vb6 to DLL written in MS C. I get result in sErr without get error, but I can see all message only in Intermediate windows of Vb6. When I make for example msgbox sErr I get only first letter of whole text. Review pic. To understand better situation.
I have a row sErr = String(255, vbNullChar) which is not seen by the picture, but this doesn’t help.
Please help – how to get this text in ordinary VB6 string ?
Thanks.
P.S: here you describe what is result of function from C declaration
7.2 GetErrorText()
const char* GetErrorText(int nError) const;
Return: The GetErrorText() function returns a pointer to a character string that contains a printable version of the error indicated by nError.
String-Mistery.png
That would work, however since it's returning you a pointer to a string you change the decleration to Long and then you can copy the content into an allocated buffer.
// Usage
Dim pErrString As Long
pErrString = GetErrorText(0)
Debug.Print PtrToStringAnsi(pErrString )
// Usage
Dim pErrString As Long
pErrString = GetErrorText(0)
Debug.Print PtrToStringAnsi(pErrString
Private Declare Function GetErrorText Lib "example.dll" ( _
ByVal nError As Long) As Long
Private Declare Sub RtlMoveMemory Lib "Kernel32.dll" ( _
ByRef pDest As Any, _
ByRef pSrc As Any, _
ByVal ByteLen As Long)
Private Declare Function lstrlenA Lib "Kernel32.dll" ( _
ByVal ptr As Long) As Long
Private Function PtrToStringAnsi(ByVal ptr As Long) As String
Dim Buffer As String
Dim cb As Long
If ptr = 0 Then
Exit Function
End If
cb = lstrlenA(ptr)
If cb > 0 Then
Buffer = String$(cb, vbNullChar)
RtlMoveMemory ByVal Buffer$, ByVal ptr&, cb
PtrToStringAnsi = Buffer
Else
PtrToStringAnsi = vbNullString
End If
End Function
ASKER
To HooKooDooKu
I can’t change source of C DLL, this is hardware card.
To edi1044
Thanks very very much for help. I was sure that I need some think like that, but was not able to write it on my self.
I use you example and found only 1 error – it again return only first letter. But I make a test and find where is problem, but again I can’t solve it, please help if you could.
cb = lstrlenA(ptr)
If cb > 0 Then
Buffer = String$(cb, vbNullChar)
Cb is 1, with immediate windows I set cb=3 and in buffer I see correct first 3 letters of message. Therefor, this cb = lstrlenA(ptr) do work fine, how to correct it ?
Again thanks!
I can’t change source of C DLL, this is hardware card.
To edi1044
Thanks very very much for help. I was sure that I need some think like that, but was not able to write it on my self.
I use you example and found only 1 error – it again return only first letter. But I make a test and find where is problem, but again I can’t solve it, please help if you could.
cb = lstrlenA(ptr)
If cb > 0 Then
Buffer = String$(cb, vbNullChar)
Cb is 1, with immediate windows I set cb=3 and in buffer I see correct first 3 letters of message. Therefor, this cb = lstrlenA(ptr) do work fine, how to correct it ?
Again thanks!
ASKER
To edi1044
Hyyym. I found a half of solution – I use Unicode version of drivers. So I change
cb = lstrlenA(ptr)
to
cb = lstrlenW(ptr)
and now I get len of string 14
Real message is:File not found
But I get F I l e n o t beacouse it count space also. How to fix this ? Simple by multiply * 2 ?
Hyyym. I found a half of solution – I use Unicode version of drivers. So I change
cb = lstrlenA(ptr)
to
cb = lstrlenW(ptr)
and now I get len of string 14
Real message is:File not found
But I get F I l e n o t beacouse it count space also. How to fix this ? Simple by multiply * 2 ?
can you pass a byte array instead of a string?
ASKER
Hyyym. Look pic. Now is same result. Is it possible in this string the separator between real chars to be some bad charter like new row or whatever and I to solve question with just remove it ?
String-Mistery-2.png
String-Mistery-2.png
Well, if you can't change the DLL, then write your own to be the interface between the DLL and your VB code. Your VB code calls your C DLL code, which in turn calls the DLL that returns the char*. Then convert the char* to a BSTR using the sample I listed before.
I like doing this for any major VB application because it gives you the flexability of doing stuff in VB and C.
I like doing this for any major VB application because it gives you the flexability of doing stuff in VB and C.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
10x. I make change and now work. You are the great! Thanks !
BSTR __declspec(dllexport) FAR PASCAL GetSomeString( int i )
{
char* pString = FunctionToGetAString( i );
return SysAllocStringByteLen( p, strlen( p ) );
}
The VB Declare will look something like this:
Public Function GetSomeString alias GetSomeString_4( I as Integer ) as String