I am trying to port a rather large source from VB6 to C#. This is no easy task - especially for me being fairly new to C#.net. This source uses numerous Windows APIs as well as numerous Types. I know that there is no equivalent to the VB6 Type in C# but I'm sure there is a way to reach the same outcome. I will post some code below to further explain my request.
VB6:
Private Type ICONDIRENTRY
bWidth As Byte
bHeight As Byte
bColorCount As Byte
bReserved As Byte
wPlanes As Integer
wBitCount As Integer
dwBytesInRes As Long
dwImageOffset As Long
End Type
Dim tICONDIRENTRY() As ICONDIRENTRY
ReDim tICONDIRENTRY(tICONDIR.idCount - 1)
For i = 0 To tICONDIR.idCount - 1
Call ReadFile(lFile, tICONDIRENTRY(i), Len(tICONDIRENTRY(i)), lRet, ByVal 0&)
Next i
I have tried using structs and classes - but no luck so far.
I would like to see a conversion of this Type structure, but if someone had any clue as to how to convert the entire thing it would be unbelievably helpful. I have spent countless hours on this small project already.
If it makes any difference, this is strictly for educational purposes only.
Thank you for any help in advance,
Evan
struct is the equivalent. You'd express it like this:
struct IconDirEntry {
public byte Width;
public byte Height;
public byte ColorCount;
public byte Reserved;
public int Planes;
public int BitCount;
public long BytesInRes;
public long ImageOffset;
}
You declare a variable like this:
IconDirEntry entry;
Generally, in C#, type prefixes are not used, nor are all caps, except possibly for constants. structs are value types in C#, so that means that they are always passed by value. It looks like you're passing them in to a method that's populating them. If you want that usage, you'll have to use classes.
I'm not exactly sure what your issue is but this is a small ex of how to use a struct.
struct aStrt
{
public int A;
public int B;
}
static void Main(string[] args)
{
aStrt saStrt;
saStrt.A = 5;
}
Your question is not clear ..
What issues are you facing when you are using either struct or class and define those field members? Are you not able to access those members using an instance created for that class ??
Else, declare the class as static and make all the members inside the class also as static , so that u can access them without any instance being created!!
Maybe you trying to get something like this?
struct IconDirEntry
{
public byte Width;
// etc...
}
IconDirEntry[] tICONDIRENTRY = new IconDireEntry[tICONDIR.idCount - 1];
Related
Working with a very large number structs as well as Arrays and Lists of structs I'm always annoyed by the the usual hurdles to reduce the number of copies of said structs when passing them to methods or working with them in diverse ways.
In addition I am forced to use structs as I need to use blittable types.
I also know about things like ErrorProne.NET which helps a lot but I'm still not fine with the Solution I currently have.
Now, with the latest C# and .NET-Versions we have the record-type which can be applied to both, structs and classes or used standalone but I can't find any clear information regarding copy-when-passing beheaviour and similar stuff and about how a record struct behaves compared to a normal struct and whether record structs can be blittable or not.
Following an Example of the structs (here record structs) I'm talking about. In the optimal case, I would even like to use them in combination with a Custom ObjectPool allowing me to re-use them without my program having to allocate the memory for new of these structs again and again while GC-ing old unused ones.
[StructLayout(LayoutKind.Sequential)]
public record struct PagedSecondaryIndexKey
{
[MarshalAs(UnmanagedType.U1)]
public SecondaryIndexType IndexType;
[MarshalAs(UnmanagedType.U8)]
public ulong Page;
[MarshalAs(UnmanagedType.Struct)]
public IndexIdentifier IndexIdentifier;
public PagedSecondaryIndexKey(ulong page, SecondaryIndexType indexType, ulong identifier1, ulong identifier2, ulong identifier3)
{
IndexType = indexType;
Page = page;
IndexIdentifier.Reset(identifier1, identifier2, identifier3);
}
}
[StructLayout(LayoutKind.Sequential)]
public record struct IndexIdentifier
{
[MarshalAs(UnmanagedType.U8)]
private ulong IndexIdentifier1;
[MarshalAs(UnmanagedType.U8)]
private ulong IndexIdentifier2;
[MarshalAs(UnmanagedType.U8)]
private ulong IndexIdentifier3;
public const int Size = 3 * sizeof(ulong);
public IndexIdentifier(ulong identifier1, ulong identifier2, ulong identifier3)
{
IndexIdentifier1 = identifier1;
IndexIdentifier2 = identifier2;
IndexIdentifier3 = identifier3;
}
public IndexIdentifier(IndexIdentifier indexKeyIndexIdentifier)
{
indexKeyIndexIdentifier.IndexIdentifier1 = IndexIdentifier1;
indexKeyIndexIdentifier.IndexIdentifier2 = IndexIdentifier2;
indexKeyIndexIdentifier.IndexIdentifier3 = IndexIdentifier3;
}
}
Tried diverse things to solve the Problems mentions, used diverse tools, did a lot of research but still havn't found the answer I'm looking for.
Basically, records just add a number of default methods to the class (ToString, Equals, etc.) but otherwise a record class behaves like a class (it's a reference type) and record struct behaves like a struct (it's a value type).
That also means that a record struct is blittable if and only if an equivalent struct would be blittable. Which basically means that a struct/record struct must not contain references to be blittable.
I have a little question about arrays of struct in C#: lets say I have a struct Foo:
struct Foo
{
public string S;
public int X;
...
...
}
and I have an array of Foo:
Foo[] arr = ...
In one method, I use arr[i] quite often, so I'd like to keep it in a local variable (the expression for i is also a little long):
var f = arr[i]
Now, my problem is that I know structs are value type, which means assignments like this cause a copy. The struct is a little big (7 strings and a bool), so I'd prefer to avoid copying in this case.
If I am not mistaken, the only way to access the struct's fields without copying the struct is to use the array directly: arr[i].S or arr[i].X, but this quickly becomes annoying to read. I'd really like to keep the array element in a local variable, but I don't want to waste performance by copying it into the variable.
Is there a way to make something like a reference variable (similar to C++) to avoid copying? If not, than I'm curious if it's something the compiler optimizes?
How should I deal with this element? Can I put it in a local variable without copying or do I have to access it through the array to avoid copying?
Thanks in advance.
You can do this in C# 7 and later using ref local variables:
using System;
public struct LargeStruct
{
public string Text;
public int Number;
}
class Test
{
static void Main()
{
LargeStruct[] array = new LargeStruct[5];
// elementRef isn't a copy of the array value -
// it's really the variable in the array
ref LargeStruct elementRef = ref array[2];
elementRef.Text = "Hello";
Console.WriteLine(array[2].Text); // Prints hello
}
}
Of course, I'd normally recommend avoiding:
Large structs
Mutable structs
Public fields (although if it's mutable, doing that via public fields is probably best)
... but I acknowledge there are always exceptions.
I'm currently migrating some VB.Net code to C#, and am quite confused about the struct in VB.NET.
Here is the code from VB which I would like to ask the equivalent in C# or some explanation.
Below is the struct format
struct Pt_Appt
{
public Pt_Appt(int pID, int aID)
{
PatientID = pID;
AppointID = aID;
}
public int PatientID;
public int AppointID;
}
Below is the code that is confusing me, I've tried and it seems creating array of struct but why negative value.
Dim pt_appts(-1) As pt_appt
It declares an empty array of type pt_appt. The upper bound is set to -1. Since the lower bound is always 0, this results in no valid indices. Arrays are re-sized via ReDim. However, this should be avoided if possible. In most cases, a List(Of T) or similar structures are more appropriate.
The C# equivalent is
Pt_Appt[] pt_appts = new Pt_Appt[0];
I want to make a list of pointers to locations that contains a certain value in the process memory of another process. The value can be a short, int, long, string, bool or something else.
My idea is to use Generics for this. I have one problem with making it, how can I tell the compiler to what type he needs to convert the byte array?
This is what I made:
public List<IntPtr> ScanProccessFor<T>(T ItemToScanFor)
{
List<IntPtr> Output = new List<IntPtr>();
IntPtr StartOffset = SelectedProcess.MainModule.BaseAddress;
int ScanSize = SelectedProcess.MainModule.ModuleMemorySize;
for (int i = 0; i < ScanSize; i++)
if (ReadMemory(SelectedProcess, StartOffset + i, (UInt16)Marshal.SizeOf(ItemToScanFor)) == ItemToScanFor)
Output.Insert(Output.Count,StartOffset + i);
return Output;
}
How can I tell the compiler that he needs to convert the byte[] to type T?
Your question is a little bit confusing, but I'll try to answer what I can
Instead of taking a generic type, I would probably write a method that takes an instance of an interface like IConvertableToByteArray or something.
public IConvertableToByteArray
{
public byte[] ToByteArray();
}
Then If you needed to allow a specific type to be compatible with that method, you could make an encapsulating class
public IntConvertableToByteArray : IConvertableToByteArray
{
public int Value{get; set;}
public byte[] ToByteArray()
{
insert logic here
}
}
You could use Marshal.StructureToPtr to get an unmanaged representation of the structure (which has to be a 'simple' structure). You might need to special case strings though.
You should also think about the alignment constraints on what you are searching for -- advancing through memory 1 byte at a time will be very slow and wasteful if the item must be 4 or 8 byte aligned.
I have a block of code that i'm trying to covert from an old qt file into C# but i'm a little unclear what is going on in the struct within the union below. I'm not sure what the ':' does... i'm guessing it sets the size but could not find any documentation on this. Also since C# does not have unions what is the best practice for converting something like this. Thank you
union uAWord
{
uAWord()
: m_AWord(0) {}
struct sBcdAWord
{
quint32 m_O :8;
quint32 m_S :2;
quint32 m_D :18;
quint32 m_SS :3;
quint32 m_P :1;
}
sBcdAWord m_F;
quint32 m_AWord;
}
This is what is called BitFields. the portion sBcdWord is a 32 bit word, and each field is a portion of that word taking respectively 8,2,18,3,1 BIT:
So the word layout is as below:
Bit0-Bit7 m_0
Bit8-Bit9 m_S
Bit10-Bit27 m_D
Bit28-Bit30 m_ss
Bit31 m_P
How to port this in C# depends if you are convettually porting the code, or if you need to PInvoke. In the case of PInvoke the best solution is probably to map sBcdAWord as an Unit32, and create some accessor strategy to mask on reading writing. If it is a code port, use separeted properties would be good unless there is special needing in memory usage saving.
That syntax is used to declare bitfields. The number is the number of bits for that value. See for example http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Flanguage%2Fref%2Fclrc03defbitf.htm
A good conversion to C# depends on the case I guess. As long as you are not too space-conscious, I'd just keep all needed values in parallel in a class.
That initializes m_aWord to 0.
To answer your other question, in C# you'd likely want a struct, and you'd need to use attributes to get union-like behavior out of it.
This particular example could be somewhat like:
[StructLayout(LayoutKind.Explicit)]
struct uAWord {
[FieldOffset(0)]
private uint theWord = 0;
[FieldOffset(0)]
public int m_P;
[FieldOffset(1)]
public int m_S;
[FieldOffset(3)]
public int m_SS;
[FieldOffset(7)]
public int m_O;
[FieldOffset(18)]
public int m_D;
public uAWord(uint theWord){
this.theWord = theWord;
}
}
The LayoutKind.Explicit indicates you will tell it where in the memory to map each field and the FieldOffset(int) tells which bit to start each field on. See this for more details. You'd assign this struct by setting the uint theWord in the constructor, then each of the other properties would access a chunk starting at a different memory address.
Unfortunately, that actually isn't correct. You'll need to use properties and do some bitmasking/shifting to get it right. Like this:
struct uAWord {
private uint theWord = 0;
public int m_P {get {return (theWord & 0x01);}}
public int m_S {get {return (theWord & 0x02) << 2;}}
public int m_SS {get {return (theWord & 0x04) << 3;}}
public int m_0 {get {return (theWord & 0x18) << 6;}}
}