Variable structure visibility in vb.net - vb.net

I've create a structure in my program like this:
Public Structure Team_Data
Public Shared punti_home As Integer
Dim punti_away As Integer
Dim goal_fatti As Integer
Dim goal_subiti As Integer
End Structure
I use the variable of this structure in a Width for valorize it after a regex parser control, and I don't encounter problems. But if I would use the structure variable in a function like a parameter, so:
pressure(punti_home)
The compiler tells me that the variables isn't declared. Why happean this?

You would need to refer to it as Team_Data.punti_home.

Related

Variable Names That are Created on runtime

Is there a way in VB to create variables that are created on run time with that are automatically named
For y As Integer = 0 To 100
Dim Varible{y} as integer
Next
You cannot create the name of a variable at runtime, but you can use a collection of variables with a specified key (name) for each element, or a class with a single public variable or property plus a name property.
Why not just use an array?
Dim Variable(100) As Integer

Why is VBA saying that it has found an 'ambiguous name'?

When compiling some code (declarations shown below) I get the error message 'Compile Error: Ambiguous name detected. SixTables'. I have looked here and elsewhere but cannot find anything that matches my problem. What appear to be the most common causes of this error, declaring two variables with identical names or giving the same name to a function and the sub that it is called from, do not apply. And yes, I know I could just change the name to something the system was happy with, but (1) I wouldn't learn what I'm doing wrong, and (2) I chose that name for a reason - it fits its purpose exactly :-)
Option Explicit
Dim ArmOfService As Byte
Dim CharacterNumber As Long
Dim CurrentTerm As Byte
Dim DecorationRollMade As Byte
Dim DecorationRollNeeded As Byte
Dim DiceSize As Byte
Dim GenAssignment
Dim GenAssignmentSwitchInt As Byte
Dim GenAssignmentSwitchOff As Byte
Dim iLoopControl
Dim jLoopControl
Dim kLoopControl
Dim LineIncrement As Integer
Dim lLoopControl
Dim Merc(100)
Dim NoOfDice As Byte
Dim OfficerPromotion(63 To 78) As Byte
Dim PromotionRollMade As Byte
Dim PromotionRollNeeded As Byte
Dim Roll As Byte
Dim SkillColumn
Dim SixTables
Dim SpecAssignmentSwitchEnd As Byte
Dim SurvivalRollMade As Byte
Dim SurvivalRollNeeded As Byte
Dim TechLevel As Byte
Dim Temp As Integer
Dim Term As Byte
Dim TestCount
Dim UnitAssignment
Dim WhichTable
Dim Year As Byte
EDIT: I'm so embarrassed that I can hardly bring myself to explain what the problem was. I knew I hadn't duplicated a name, since I was only using it once - as a function! Thanks all for your help, I'm now going to go and hide my face in shame...
From MSDN :
More than one object in the same scope may have elements with the
same name.
Module-level identifiers and project-level identifiers (module names
and referenced project names) may be reused in a procedure, although
it makes programs harder to maintain and debug. However, if you want
to refer to both items in the same procedure, the item having wider
scope must be qualified. For example, if MyID is declared at the
module level of MyModule , and then a procedure-levelvariable is
declared with the same name in the module, references to the
module-level variable must be appropriately qualified:
Dim MyID As String
Sub MySub
MyModule.MyID = "This is module-level variable"
Dim MyID As String
MyID = "This is the procedure-level variable"
Debug.Print MyID
Debug.Print MyModule.MyID
End Sub
An identifier declared at module-level conflicts with a procedure name.
For example, this error occurs if the variable MyID is declared at
module level, and then a procedure is defined with the same name:
Public MyID
Sub MyID
. . .
End Sub
Having had this issue many times, and not fully understanding why, I think there is an important fact that I have tested, and someone can confirm. It may be obvious to professional programmers, but I place this here for those that seek these answers on discussions, who are usually not professional programmers.
A variable declared within a sub() is not "declared" (memory assigned) until that sub() is executed. And when the execution of that sub() is complete, the memory is released. Until now, I thought Public variables acted in similar way; available to any module that used it, --BUT only existing as long as the module where they were declared was still executing.
However, for any Public variable who's declaration line is in any module in the workbook, that variable is declared and available at the execution of any module within the workbook, even if the module where the Public declaration exists is never called or executed.
Therefore, if you have a Public variable declaration in one module, and then again in a separate module that you plan to run independent of the first, Excel still sees 2 declarations for the same variable, and thus it is ambiguous.
To prove it, you can create a blank module within a workbook project, and add absolutely nothing except two Public declaration lines,
Public VariableX as String
Public VariableY as Integer
and those variables will be declared and available throughout the project, for any sub() executed. This fact is also probably the reason for the tip about minimizing the use of public variables.
Again, this may have been kindergarten level information for professional programmers, but most on this are not pros, and have to learn these lessons the hard way, or through discussion boards like this. I hope this helps someone.

How can a structure with reserved space be marshalled?

Problem:
I have a struct of a fixed size that I'm trying to marshal. This struct contains a number of useful fields for the current version of the struct and a specified amount of unused space at the end that is reserved for future modifications.
How should I design this structure so that the size of the reserved space will be automatically updated when I modify the structure?
While the following would solve my problem
'Variable size structure
<StructLayout(LayoutKind.Sequential, Pack:=1)>
Structure UsefulData
Dim foo As SByte
Dim bar As Integer
Dim foobar As Short
End Structure
Const MAX_SIZE As Integer = 20
'Fixed size structure
<StructLayout(LayoutKind.Sequential, Pack:=1, Size:=MAX_SIZE>
Structure Data
Dim current As UsefulData
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=MAX_SIZE-System.Runtime.InteropServices.Marshal.SizeOf(GetType(UsefulData)))>
Dim reserved As SByte()
End Structure
but doesn't compile as System.Runtime.InteropServices.Marshal.SizeOf(GetType(UsefulData)) is not a constant expression. Any ideas?
Upon further reflection on this problem I've come to question the validity of my desire to expose the reserved space at the end of the struct. In reality nothing should ever reference the reserved section. If something ever needed to, then the correct approach would be to modify the structure itself to expose the relevant parts of the reserved space.
Consequently the structure should look as follows:
<StructLayout(LayoutKind.Sequential, Size:=20, Pack:=1)>
Structure Data
Dim foo As SByte
Dim bar As Integer
Dim foobar As Short
End Structure
While I don't think hard-coding the array length is the ideal solution, I'm placing this answer here in case there are no other alternatives.
Private const TOTAL_SIZE As Integer = 20
Private const RESERVED_SIZE As Integer = 7
<StructLayout(LayoutKind.Sequential, Pack:=1)>
Structure Data
Dim foo As SByte
Dim bar As Integer
Dim foobar As Short
<MarshalAs(UnManagedType.ByValArray, SizeConst:=RESERVED_SIZE)>
Dim reserved As SByte()
End Structure
I could then add either a unit test or custom build action to ensure that System.Runtime.InteropServices.Marshal.Sizeof(GetType(Data)) = TOTAL_SIZE.

How do I use a Structure in multiple classes?

I want to use this Structure in multiple .vb files within my project:
Structure MyStruct
Dim Name As String
Dim Good As Boolean
End Structure
If I define it in one file, the other files can't use it. How do I define it globally?
Make this Structure Public
Public Structure MyStruct
Dim Name As String
Dim Good As Boolean
End Structure
and add this Structure in a Module File so that it can be accessed from anywhere, but give the Module name as a namespace in your class
using Module1.vb

VB.net Passing a structure to unmanaged dll

I'm migrating some VB6 code to VB.net,
the code contains a structure that contains 1d arrays, 2d arrays, and few other variables.
The general outline of the Vb.net structure is as under
Public Structure Test
Dim a As Single
Dim b As Single
Dim c As Single
<VBFixedArray(2)> Dim arr1() As Single
<VBFixedArray(2, 2)> Dim mdarr1(,) As Single
<VBFixedArray(4)> Dim arr2() As Byte
<VBFixedArray(4)> Dim arr3() As Short
<VBFixedArray(3, 2)> Dim mdarr2(,) As Integer
Dim d As Integer
Dim e As Decimal
End Structure
The call to the dll is declared as under
Public Declare Sub getState Lib "val.dll" (ByRef state As Test)
Elsewhere on this site I realized that we have to "marshal" the structure to allow it to be compatible with the unmanaged code that is about to accept it.
However I still receiving runtime errors when running the code, I don't have any clue of how to use the System.Runtime.InteropServices.Marshal class.
What would be the correct way to pass this structure to the dll?
EDIT:
The original VB6 data type is
Public Type Test
a As Single
b As Single
c As Single
arr1(0 To 2) As Single
mdarr1(0 To 2, 0 To 2) As Single
arr2(0 To 4) As Byte
arr3(0 To 4) As Integer
mdarr2(0 To 3, 0 To 2) As Long
d As Long
e As Currency
End Type
Do you have the source code for getState in the val.dll? If it's written in C or C++, and you have the source code or even just the headers, you could use the P/Invoke Assistant to automatically generate your VB.Net code.
Alternatively... (and please do post the original VB6 structure!)
You might need to allocate the arrays before calling getState, e.g. state.arr1 = {0.0, 0.0} etc.
The Decimal variable e could cause you a problem. In VB6 this was probably a Currency variable, and Decimal is not an exact equivalent as far as I can remember. There will be a way to tell VB.Net to marshal it like a Currency. Perhaps adding an attribute like this...
Sample code:
Imports System.Runtime
Public Structure Test
''blah blah
<InteropServices.MarshalAs(InteropServices.UnmanagedType.Currency)> _
Dim e As Decimal
''blah blah