Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How to get correct string return from C DLL ?

Posted on 2010-11-12
9
Medium Priority
?
325 Views
Last Modified: 2012-05-10
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
0
Comment
Question by:dvplayltd
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
  • 2
  • +1
9 Comments
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 34122978
VB uses a type of string known as a BSTR.  If you have control over the C Source Code, you want to change that code to return you a BSTR.  Here's an example function:

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
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 34123110
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)
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

Open in new window

0
 

Author Comment

by:dvplayltd
ID: 34123445
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!
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:dvplayltd
ID: 34123516
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 ?
0
 
LVL 46

Expert Comment

by:aikimark
ID: 34123547
can you pass a byte array instead of a string?
0
 

Author Comment

by:dvplayltd
ID: 34123591
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
0
 
LVL 16

Expert Comment

by:HooKooDooKu
ID: 34123593
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.
0
 
LVL 29

Accepted Solution

by:
nffvrxqgrcfqvvc earned 2000 total points
ID: 34123958
If your dealing with a unicode pointer then replace it with the following.
Private Declare Function lstrlenW Lib "Kernel32.dll" ( _
    ByVal ptr As Long) As Long

Private Function PointerToStringUni(ByVal lpPointer As Long) As String
    Dim Buffer()    As Byte
    Dim lpSize      As Long
    
    If lpPointer = 0 Then
        Exit Function
    End If
    
    lpSize = lstrlenW(lpPointer) * 2
    
    If lpSize <> 0 Then
        ReDim Buffer(lpSize) As Byte
        RtlMoveMemory Buffer(0), ByVal lpPointer, lpSize
        PointerToStringUni = Buffer
    Else
        PointerToStringUni = vbNullString
    End If
    
    Erase Buffer
End Function

Open in new window

0
 

Author Closing Comment

by:dvplayltd
ID: 34124012
10x. I make change and now work. You are the great! Thanks !
0

Featured Post

New benefit for Premium Members - Upgrade now!

Ready to get started with anonymous questions today? It's easy! Learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses

670 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question