Microsoft KB Archive/187912

= How To Pass a String Between Visual Basic and Your C DLL =

Article ID: 187912

Article Last Modified on 3/3/2005

-

APPLIES TO


 * Microsoft Visual Basic 5.0 Learning Edition
 * Microsoft Visual Basic 6.0 Learning Edition
 * Microsoft Visual Basic 5.0 Professional Edition
 * Microsoft Visual Basic 6.0 Professional Edition
 * Microsoft Visual Basic 5.0 Enterprise Edition
 * Microsoft Visual Basic 6.0 Enterprise Edition
 * Microsoft Visual C++ 5.0 Enterprise Edition
 * Microsoft Visual C++ 5.0 Professional Edition

-



This article was previously published under Q187912



SUMMARY
When creating a C dynamic-link library (DLL) for use with Visual Basic, it is important to remember that C and Visual Basic treat strings differently. You must take every precaution to ensure that all strings are passed correctly; otherwise, a fatal error may occur. This article will show you how to write a C DLL that takes a string as a parameter to a function, and how to call the exported function from a Visual Basic application.



MORE INFORMATION
In order to develop your C DLL, it is important to know how Visual Basic handles strings internally in order to know how they will be passed to your DLL functions. Most C functions expect a string to be a null-terminated, ASCII character array. But Visual Basic uses a type-safe Automation string called a BSTR. For the Win32 platform, a BSTR is a long pointer to an allocated memory structure containing a Unicode character string and a 32- bit integer prefix that stores the length of the string.

You can ignored most of this difference, because Visual Basic will automatically convert any Unicode BSTRs to ASCII before passing them to an external function. The problem, however, is with the parameter itself. By default, Visual Basic passes all variables by reference, including strings. Because a BSTR variable is a pointer to a string, when Visual Basic passes it by reference it is actually passing a pointer to a pointer to a string. Most C functions simply expect a pointer to a string (such as LPSTR).

Create Your C DLL: Step-by-Step Example
 Open Visual C++ 5.0 and click New on the File menu. On the Projects tab, select "Win32 Dynamic-Link Library" and name the project "StrSamp." Once again, click New on the File menu, and select "C++ Source File." On the Files tab, name the file "StrSamp.c," and press OK. Repeat step 2 and this time choose "Text File" as the file type. Name the file "StrSamp.def," and press OK.  Next, add the following code to "StrSamp.c:" #include 

void __stdcall DisplayStringByVal(LPCSTR pszString) {        //pszString is a pointer to a string MessageBox(NULL, pszString, "Display String ByVal",                  MB_OK | MB_ICONINFORMATION); }

void __stdcall DisplayStringByRef(LPCSTR* ppszString) {        //ppszSting is a pointer to a pointer to a string MessageBox(NULL, *ppszString, "Display String ByRef",                  MB_OK | MB_ICONINFORMATION); }

void __stdcall FillString(LPSTR pszString, LONG cSize) {        // Create a temp buffer with our string char buffer[] = "Hello from the C DLL!";

// Copy our temp string to pszString // but check the size to make sure we have a buffer // big enough to hold the entire string. if (cSize > strlen(buffer)) strcpy(pszString, buffer); }

int __stdcall InStrRev(LPCSTR pszString, short iChar) {        // This function is similar to Visual Basic's InStr function // except that it searches for the given ASCII character from // right to left, returning the character position of the // last occurrence (rather than the first) of the character // in the string. char* pszTmp; int nRet = 0;

// Scan for iChar in pszString backwards pszTmp = strrchr(pszString, (int)iChar); if(pszTmp != NULL) nRet = pszTmp - pszString + 1;

return nRet; }

  To make the functions exportable, add the following to "StrSamp.def:" LIBRARY StrSamp DESCRIPTION 'Microsoft KB Sample DLL' EXPORTS DisplayStringByVal DisplayStringByRef FillString InStrRev

 Compile your DLL from the Build menu. When complete, copy the new DLL to your Visual Basic directory for testing.</li></ol>

The VB Test Application: Step-by-Step Example
<ol> Create a Standard Project in Visual Basic and name it "StrTest." Form1 is created by default.</li> Add three CommandButtons to Form1.</li>  In the code window for Form1, add the following to the General Declarations section: Option Explicit

Private Declare Sub DisplayStringByRef Lib "StrSamp.dll" _ (sMyString As String) Private Declare Sub DisplayStringByVal Lib "StrSamp.dll" _ (ByVal sMyString As String) Private Declare Sub FillString Lib "StrSamp.dll" _ (ByVal sMyString As String, ByVal cBufferSize As Long) Private Declare Function InStrRev Lib "StrSamp.dll" _ (ByVal sMyString As String, ByVal iChar As Integer) _ As Long

Note that most of the strings are declared ByVal. This does not mean that you are passing these strings by value; rather, you are passing the value of the BSTR variable by value (remember that a BSTR variable is a pointer to a string). So the ByVal keyword has the effect of passing a long pointer to a string (LPSTR), just what the C functions expect.

</li>  Add the following code to the click events for each of the CommandButtons: Private Sub Command1_Click Dim sTestString1 As String Dim sTestString2 As String

sTestString1 = "This is my string passed to the dll by value." DisplayStringByVal sTestString1

sTestString2 = "This is my string passed to the dll by reference." DisplayStringByRef sTestString2

End Sub

Private Sub Command2_Click Dim sFillTest As String

sFillTest = Space$(260) FillString sFillTest, 260 MsgBox Trim$(sFillTest), vbInformation, "Fill String" End Sub

Private Sub Command3_Click Dim sPathString As String Dim sMsg As String Dim lCharPosition As Long

sPathString = "C:\My Documents\Temp\Item.txt" lCharPosition = InStrRev(sPathString, Asc("\"))

If CBool(lCharPosition) Then sMsg = "The file '" & Mid$(sPathString, lCharPosition + 1) sMsg = sMsg & "' is at this location:" & vbCrLf & vbCrLf sMsg = sMsg & Left$(sPathString, lCharPosition - 1) MsgBox sMsg, vbInformation, "InStrRev" Else MsgBox "Cannot find '/' in " & sPathString, vbCritical End If

End Sub

</li> Press the F5 key to run the Visual Basic project in the IDE.

NOTE: If you receive an error message, it may be because Visual Basic cannot find your DLL. Make sure you have copied it to the Visual Basic directory before you run your test application.</li></ol>

<div class="references_section">