Microsoft KB Archive/194609: Difference between revisions
m (Text replacement - "&" to "&") |
m (Text replacement - """ to """) |
||
Line 79: | Line 79: | ||
<ol> | <ol> | ||
<li>Open Visual C++ and select File|New. On the Projects tab, select | <li>Open Visual C++ and select File|New. On the Projects tab, select "Win32 Dynamic-Link Library" and name the project "UDTArray."</li> | ||
<li>Select File|New again. On the Files tab, select | <li>Select File|New again. On the Files tab, select "C++ Source File," name the file "UDTArray.c," and click OK.</li> | ||
<li>Repeat step 2 and this time choose | <li>Repeat step 2 and this time choose "Text File" as the file type. Name the files "UDTArray.def" and "UDTArray.odl," respectively.</li> | ||
<li><p>Next, add the following code to UDTArray.c:</p> | <li><p>Next, add the following code to UDTArray.c:</p> | ||
<pre class="codesample"> #include <windows.h> | <pre class="codesample"> #include <windows.h> | ||
Line 100: | Line 100: | ||
SysFreeString((t+i)->str ); // free the string passed in | SysFreeString((t+i)->str ); // free the string passed in | ||
(t+i)->str = SysAllocString(OLESTR( | (t+i)->str = SysAllocString(OLESTR("Changed.")); | ||
} | } | ||
Line 112: | Line 112: | ||
<pre class="codesample"> [ | <pre class="codesample"> [ | ||
uuid(D6229080-2CC3-11d2-9FD8-00C04F8EF4D4), | uuid(D6229080-2CC3-11d2-9FD8-00C04F8EF4D4), | ||
helpstring( | helpstring("Pass Array of UDTs Helper") | ||
] | ] | ||
Line 125: | Line 125: | ||
[ | [ | ||
helpstring( | helpstring("test"), | ||
dllname( | dllname("UDTArray.dll") | ||
] | ] | ||
Line 132: | Line 132: | ||
{ | { | ||
[ | [ | ||
helpstring( | helpstring("Modify the elements of array"), | ||
entry( | entry("ModifyStruct") | ||
] | ] | ||
void _stdcall ModifyStruct | void _stdcall ModifyStruct | ||
Line 144: | Line 144: | ||
</pre></li> | </pre></li> | ||
<li>Go to Project|Settings, click the C/C++ Tab, and then choose | <li>Go to Project|Settings, click the C/C++ Tab, and then choose "Code Generation" from the Category dropdown box. Change the "Struct Member Alignment" to be "4 Bytes" because Visual Basic uses 4 bytes alignment And Visual C++ uses 8 bytes by default.</li> | ||
<li>Compile your DLL by choosing | <li>Compile your DLL by choosing "Rebuild All" from the Build menu. When complete, copy the new DLL (UDTArray.dll) to your Visual Basic directory for testing.</li></ol> | ||
=== Step-by-Step Example - The Visual Basic Client App === | === Step-by-Step Example - The Visual Basic Client App === | ||
Line 160: | Line 160: | ||
t(0).l = 1 | t(0).l = 1 | ||
t(0).str = | t(0).str = "test1" | ||
t(1).l = 2 | t(1).l = 2 | ||
t(1).str = | t(1).str = "Test2" | ||
i = UBound(t) - LBound(t) + 1 | i = UBound(t) - LBound(t) + 1 | ||
ModifyStruct t(0), i 't(0)'s address will be passed to C | ModifyStruct t(0), i 't(0)'s address will be passed to C | ||
MsgBox | MsgBox "t(1).l = " & t(1).l & vbCrLf & "t(1).str = " & t(1).str | ||
End Sub | End Sub | ||
Line 182: | Line 182: | ||
For detailed information on how to create a C DLL and use it in Visual Basic, please see the following articles:<br /> | For detailed information on how to create a C DLL and use it in Visual Basic, please see the following articles:<br /> | ||
<br /> | <br /> | ||
"DLLs for Beginners" in the Microsoft Developer Network (MSDN) Library<br /> | |||
<br /> | <br /> | ||
"VB5DLL.DOC" located on the VB5 CD-ROM in the "Tools\Docs" directory<br /> | |||
<br /> | <br /> | ||
For more information on using a type library to declare C/C++ functions in Visual Basic, see the following article in the Microsoft Knowledge Base:<br /> | For more information on using a type library to declare C/C++ functions in Visual Basic, see the following article in the Microsoft Knowledge Base:<br /> |
Latest revision as of 12:44, 21 July 2020
Article ID: 194609
Article Last Modified on 7/1/2004
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++ 6.0 Enterprise Edition
- Microsoft Visual C++ 5.0 Professional Edition
- Microsoft Visual C++ 6.0 Professional Edition
- Microsoft Visual C++ 6.0 Standard Edition
This article was previously published under Q194609
SUMMARY
When you are working with an array of User-Defined types (UDTs) in Visual Basic, you may want to pass the array to a C/C++ DLL. However, the array cannot be passed directly because SAFEARRARYs are limited to Automation- safe data types, and a UDT is not a standard Automation data type.
Moreover, if the UDT contains variable length strings, you cannot pass a pointer to the first member of the array because Visual Basic will create a temporary copy of the member in order to handle normal UNICODE to ANSI conversion of strings.
This article demonstrates one way to bypass these problems and successfully pass an array of UDTs with variable length strings to C/C++ DLLs.
MORE INFORMATION
The solution provided here relies on the type library to prevent Visual Basic from copying the content of the array to the temporary space and transforming the strings between ANSI and UNICODE. See the REFERENCES section below for more information on this topic.
The UDT in this sample is:
Type TestUDT l As Long str As String End Type
Step-by-Step Example - Create the DLL and Type Library
- Open Visual C++ and select File|New. On the Projects tab, select "Win32 Dynamic-Link Library" and name the project "UDTArray."
- Select File|New again. On the Files tab, select "C++ Source File," name the file "UDTArray.c," and click OK.
- Repeat step 2 and this time choose "Text File" as the file type. Name the files "UDTArray.def" and "UDTArray.odl," respectively.
Next, add the following code to UDTArray.c:
#include <windows.h> #include <oleauto.h> struct tagTestUDT { long l; BSTR str; } TestUDT; void __stdcall ModifyStruct(struct tagTestUDT *t, long nTotalItem) { // modify the last element long i = nTotalItem - 1; // the array begins from 0 (t+i)->l = 200; SysFreeString((t+i)->str ); // free the string passed in (t+i)->str = SysAllocString(OLESTR("Changed.")); }
To make the functions exportable, add the following to UDTArray.def:
EXPORTS ModifyStruct
Declare your functions in a type library by adding the following to UDTArray.odl:
[ uuid(D6229080-2CC3-11d2-9FD8-00C04F8EF4D4), helpstring("Pass Array of UDTs Helper") ] library PassUDTLib { //definition of the UDT typedef struct tagTestUDT { long l; BSTR str; }TestUDT; [ helpstring("test"), dllname("UDTArray.dll") ] module structDLL { [ helpstring("Modify the elements of array"), entry("ModifyStruct") ] void _stdcall ModifyStruct ( [in, out] TestUDT* t, [in] long nTotalItem ); }; };
- Go to Project|Settings, click the C/C++ Tab, and then choose "Code Generation" from the Category dropdown box. Change the "Struct Member Alignment" to be "4 Bytes" because Visual Basic uses 4 bytes alignment And Visual C++ uses 8 bytes by default.
- Compile your DLL by choosing "Rebuild All" from the Build menu. When complete, copy the new DLL (UDTArray.dll) to your Visual Basic directory for testing.
Step-by-Step Example - The Visual Basic Client App
- Open Visual Basic and create a new Standard EXE Project. Form1 is created by default.
- From the Project menu, select References to call up the References dialog box, and then click Browse. Find the UDTArray.tlb file generated for your DLL.
Add a CommandButton to Form1 and then add the following code to the code window for Form1:
Private Sub Command1_Click() ' Note: You do not need to redefine TestUDT because it is in ' the type library we added to our project. Dim t(0 To 1) As TestUDT Dim i as long t(0).l = 1 t(0).str = "test1" t(1).l = 2 t(1).str = "Test2" i = UBound(t) - LBound(t) + 1 ModifyStruct t(0), i 't(0)'s address will be passed to C MsgBox "t(1).l = " & t(1).l & vbCrLf & "t(1).str = " & t(1).str End Sub
- Run the Visual Basic application and click the CommandButton. The message box displayed indicates that the last element of the array has been changed.
REFERENCES
For detailed information on how to create a C DLL and use it in Visual Basic, please see the following articles:
"DLLs for Beginners" in the Microsoft Developer Network (MSDN) Library
"VB5DLL.DOC" located on the VB5 CD-ROM in the "Tools\Docs" directory
For more information on using a type library to declare C/C++ functions in Visual Basic, see the following article in the Microsoft Knowledge Base:
189133 : How To Make C DLL More Accessible to VB with a Type Library
For additional information, please see the following articles in the Microsoft Knowledge Base:
142840 : Visual Basic Requirements for Exported DLL Functions
171583 : How To Fill a 32-bit VBA Array of UDType via a Visual C++ DLL
Keywords: kbhowto kbdll kbstring kbcode KB194609