Hi,
I need to be able to pass a structure to a DLL that has arrays of fields of fixed length in it.
In old VB6 this could be done by having types with types
type repeatingRecord
field1 as string * 2
field2 as string * 5
end type
type maintype
field1 as string * 7
records(10) as repeatingRecord
end type
In .NET types become structures and fixed length strings no longer exist. However the attributes 'VBFixedString' and MarshalAs will solve this problem for simple structures.
However it still does not solve my problem for arrays. .NET will not allow fixed length arrays ......
How do I pass the equivalent in .NET to unmanaged code in a DLL
Regards
Michael

Passing a structure with arrays of fixed length strings to a DLL
alok ranjan
The VBFixedString and VBFixedArray are meant to be used with VB File IO routines (FileOpen, FilePut, etc).
For passing structures with fixed size strings through P/Invoke (Declare statement method) you probably need to use the ByValTStr type on the marshalas attribute instead of ByValArray:
MarshalAs(Runtime.InteropServices.UnmanagedType.ByValTStr,sizeconst:=5)
I don't really remember if the Ansi vs Unicode definition on declares affects the size of the characters here - you may also need to add a StructLayoutAttribute to the structure if you can't get the correct Char size.
Malla
Hi,
ByValTStr does not work - this is as per the Microsoft Press VB6 to .NEt upgrade book. My testing supports this - changing the strings to char arrays and using the VBFixedString attribute worked.
Regards
Michael Green
alan_k
My test dll relevant code:
struct
repeatingRecord{
char field1[2];
char field2[5];
};
struct C1
{
char field1[7];
repeatingRecord records[10];
};
extern "C"
{
TESTDLL_API int fnTestDLL(C1 arg);
}
TESTDLL_API
int fnTestDLL(C1 arg){
MessageBoxA(0,arg.field1,"Title1", MB_OK);
MessageBoxA(0,arg.records[9].field1 ,"Title2", MB_OK);
MessageBoxA(0,arg.records[9].field2 ,"Title3", MB_OK);
return 42;
}
On the vb side:
Imports
System.Runtime.InteropServicesModule Module1
Structure repeatingRecord
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=2)> Dim field1 As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=5)> Dim field2 As String
End Structure Structure maintype
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=7)> Dim field1 As String
<MarshalAs(UnmanagedType.ByValArray, sizeconst:=10)> Dim records() As repeatingRecord
End Structure Declare Ansi Function fnTestDLL Lib "C:\Documents and Settings\amoura\My Documents\Visual Studio 2005\Projects\TestDLL\debug\testdll.dll" (ByVal arg As maintype) As Integer Sub Main()
Dim c As maintype
c.field1 = "123456"
c.records = New repeatingRecord(10) {}
For i As Integer = 0 To 9
c.records(i).field1 = "1"
c.records(i).field2 = "1234"
Next
fnTestDLL(c)
End Sub
End
ModuleThis seems to work as expected - Let me know if this still isn't what you're looking for.
Francy
Hi,
Given I've already had a look at this area (hence my comments on VBFixedString etc) a little more precise guidance would be appreciated e.g. a few URLs.......
Regards
Michael
Karthick Sukumaran
The following may help show the change from VB6 to VB.Net with regard to calling API's
This is a simple example sending a file to the recycle bin but it defines a structure used in the API.
http://www.developerfusion.co.uk/show/4334/
fixed length strings and API functions
http://groups.google.com/group/microsoft.public.dotnet.languages.vb/browse_thread/thread/282a4b3969498eb5/f7e6db7474437cb2%23f7e6db7474437cb2 sa=X&oi=groupsr&start=0&num=3
Jvalente
Hi,
I still can't get this to work.
The .NET structures are as follows. The only way I can get this to work is if I convert the array of sub-structures to dummy fields in the main structure. Then the data is correctly passed to the API. If I pass as is I get a 'Parameter Incorrect' error message.
Structure repeatingRecord
<VBFixedString(2), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2)> _
Public field1 As String
<VBFixedString(5), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=5)> _
Public field2 As String
End Structure
Structure maintype
<VBFixedString(7), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=7)> _
Public field1 As String
<VBFixedArray(10)> Dim records() As repeatingRecord
'UPGRADE_TODO: "Initialize" must be called to initialize instances of this structure. Click for more: 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm keyword="vbup1026"'
Public Sub Initialize()
ReDim records(10)
End Sub
End Structure
Grozen
Hi,
sorry - but neither of these links address the core issue here which is how to pass to correctly arrays of subordinate structures.
Regards
Michael Green
Varsha
milTash
Micheal...
Take a look at interop services and Marshalling. There are way to describe those string that you won't find anywhere else.
Margriet
The Help files is what I was referring to......
I refer to them often and the fora have settle into the phrase "have a look at" to mean either help or the object browser. In this case, help will be better.